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

4355 lines
137 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: util.cxx
//
// Contents: Implementation of utilities for common class library and for
// tests.
//
// Functions: - GenerateRandomName
// - GetVirtualCtrNodeForTest
// - GetVirtualStmNodeForTest
// - DestroyStorage
// - DestroyStream
// - AddStorage
// - AddStream
// - CalculateCRCForName
// - CalculateCRCForDataBuffer
// - CalculateInMemoryCRCForStg
// - CalculateInMemoryCRCForStm
// - ReadAndCalculateDiskCRCForStm
// - CalculateDiskCRCForStg
// - EnumerateInMemoryDocFile
// - OpenRandomVirtualCtrNodeStg
// - CloseRandomVirtualCtrNodeStg
// - ParseVirtualDFAndCloseOpenStgsStms
// - ParseVirtualDFAndCommitAllOpenStgs
// - CalculateCRCForDocFile
// - CalculateCRCForDocFileStmData
// - TStringToOleString
// - EnumerateDiskDocFile
// - GenerateVirtualDFFromDiskDF
// - GenerateRemVirtualDFTree [local to this file]
// - GenVirtualCtrNode [local to this file]
// - GenVirtualStmNode [local to this file]
// - PrivAtol
// - GenerateRandomString
// - GenerateRandomStreamData
// - ParseVirtualDFAndOpenAllSubStgsStms
// - CommitRandomVirtualCtrNodeStg
//
// History: 17-Apr-96 Narindk Created.
// 2-Feb-97 SCousens Added for Cnvrs/NSS
// 31-Mar-98 SCousens Added GenerateRandomStreamData
//
//--------------------------------------------------------------------------
#include <dfheader.hxx>
#pragma hdrstop
// Debug Object declaration
DH_DECLARE;
// CRC 32 Bitwise lookup table, logic taken from CRC-32 description in
// 'C Programmer's Guide to Netbios' book.
ULONG aulCrc[256] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
// Functions local to this file
HRESULT GenerateRemVirtualDFTree(
VirtualCtrNode *pvcnParent,
LPSTORAGE pIStgParent);
HRESULT GenVirtualCtrNode(
LPTSTR ptcsName,
VirtualCtrNode **ppvcnNew);
HRESULT GenVirtualStmNode(
LPTSTR ptcsName,
DWORD cbSize,
VirtualStmNode **ppvsnNew);
//+-------------------------------------------------------------------------
// Function: GenerateRandomName
//
// Synopsis: Generates a random name using datagen object.
//
// Arguments: [pgds] - Pointer to DG_STRING object.
// [pptszName] - Pointer to pointer to returned string.
// [ulMinLen] - Minimum length of string
// [ulMaxLen] - Maximum length of string
//
// Returns: HRESULT. S_OK if everything goes ok, error code otherwise.
//
// History: 11-Nov-96 BogdanT Changed the DG_UNICODE ptr. to DG_STRING
// 17-Apr-96 NarindK Created.
//
// Notes: BUGBUG: This function need to be enhance to handle different
// character sets.
// Please note that the name generated may have an extension b/w
// 0 and FILEEXT_MAXLEN besides the length of name b/w ulMinLen and
// ulMax Len.
//--------------------------------------------------------------------------
HRESULT GenerateRandomName(
DG_STRING *pgds,
ULONG ulMinLen,
ULONG ulMaxLen,
LPTSTR *pptszName)
{
HRESULT hr = S_OK;
ULONG cTemp = 0;
USHORT usErr = 0;
ULONG ulActMaxLen = 0;
ULONG ulActMinLen = 0;
ULONG ulNameLen = 0;
ULONG ulExtLen = 0;
LPTSTR ptszName = NULL;
LPTSTR ptszExt = NULL;
LPWSTR pwszName = NULL;
LPWSTR pwszExt = NULL;
TCHAR ptszFATCharSet[FAT_CHARSET_SIZE];
// TCHAR ptszOFSCharSet[OFS_CHARSET_SIZE];
LPWSTR pwszFATCharSet = NULL;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("GenerateRandomName"));
DH_VDATEPTRIN(pgds, DG_STRING) ;
DH_VDATEPTROUT(pptszName, LPTSTR) ;
DH_ASSERT(NULL != pgds);
DH_ASSERT(NULL != pptszName);
if (S_OK == hr)
{
// Initialize out parameter.
*pptszName = NULL;
// Sanity check. Min length for name must be <= maximum length, if it
// isn't then make maximum length equal to minimum length.
if (ulMaxLen < ulMinLen)
{
ulMaxLen = ulMinLen;
}
// If Maximum length provided is 0, then default maximum length would
// be used. If Minimum length provided is zero, then 1 would be used
// for it.
// BUGBUG: We are using default maximum length for FAT system.
ulActMaxLen = (ulMaxLen == 0 ? DEF_FATNAME_MAXLEN : ulMaxLen);
ulActMinLen = (ulMinLen == 0 ? 1 : ulMinLen);
// '\0', '\', '/', and ':' are invalid for IStorage/IStream names
// (For doc file)
// '*', '"' '<' '>' '?' are invalid for IStorage/IStream names on OFS
// Initialize valid character set for FAT file names
_tcscpy(ptszFATCharSet, _TEXT("abcdefghijklmnopqrstuvwxyz"));
_tcscat(ptszFATCharSet, _TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
_tcscat(ptszFATCharSet, _TEXT("0123456789"));
//BUGBUG: Check if these characters are not valid for IStorage/IStream
// names.
// _tcscat(ptszFATCharSet, L"_^$~!#%&-{}()@'`");
// Initialize valid character set for other file names. BUGBUG: Not
// using OFS character set at present.
// for (TCHAR wch = 0x01; wch <= 0x7f; wch++)
// {
// if (wch != L'\\' && wch != L'/' && wch != L'*' && wch != L'?')
// {
// ptszOFSCharSet[cTemp++] = wch;
// }
// }
// ptszOFSCharSet[cTemp] = NULL;
// Call DataGen to generate a random file name
// BUGBUG: We are using FAT character set to generate random names.
#ifdef _MAC
usErr = pgds->Generate(
(UCHAR **)&ptszName, // force compiler to chose the right
(UCHAR *)ptszFATCharSet, // version of Generate
ulActMinLen,
ulActMaxLen);
#else
if(S_OK == hr)
{
// Convert TCHAR to WCHAR
hr = TStrToWStr(ptszFATCharSet, &pwszFATCharSet);
DH_HRCHECK(hr, TEXT("TStrToWStr")) ;
}
usErr = pgds->Generate(
&pwszName,
pwszFATCharSet,
ulActMinLen,
ulActMaxLen);
#endif //_MAC
if (usErr != DG_RC_SUCCESS) // DataGen error
{
hr = E_FAIL;
}
}
if (S_OK == hr)
{
// Generate a random extension
#ifdef _MAC
usErr = pgds->Generate(
(UCHAR **)&ptszExt, // force compiler to chose the right
(UCHAR *)ptszFATCharSet, // version of Generate
0,
FILEEXT_MAXLEN);
#else
usErr = pgds->Generate(
&pwszExt,
pwszFATCharSet,
0,
FILEEXT_MAXLEN);
#endif //_MAC
if (usErr != DG_RC_SUCCESS) // Failed to generate extension
{
hr = E_FAIL;
delete pwszName;
pwszName = NULL;
}
}
#ifndef _MAC
// In MAC version we don't use the WSZs so skip the conversions
if(S_OK == hr)
{
//Convert WCHAR to TCHAR
hr = WStrToTStr(pwszName, &ptszName);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
}
if((S_OK == hr) && (NULL != *pwszExt))
{
//Convert WCHAR to TCHAR
hr = WStrToTStr(pwszExt, &ptszExt);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
}
#endif //_MAC
if (S_OK == hr)
{
ulNameLen = _tcslen(ptszName);
if(NULL != ptszExt)
{
ulExtLen = _tcslen(ptszExt);
// If the length of the extension > 0, a '.' will be added.
if (ulExtLen > 0)
{
ulNameLen += ulExtLen + 1;
}
}
// Construct the full name
*pptszName = new TCHAR[ulNameLen + 1];
if(NULL == *pptszName)
{
hr = E_OUTOFMEMORY;
}
}
if (S_OK == hr)
{
_tcscpy(*pptszName, ptszName);
if (ulExtLen > 0)
{
_tcscat(*pptszName, _TEXT("."));
_tcscat(*pptszName, ptszExt);
}
}
// Clean up
if (NULL != ptszExt)
{
delete ptszExt;
ptszExt = NULL;
}
if (NULL != ptszName)
{
delete ptszName;
ptszName = NULL;
}
if (NULL != pwszExt)
{
delete pwszExt;
pwszExt = NULL;
}
if (NULL != pwszName)
{
delete pwszName;
pwszName = NULL;
}
if (NULL != pwszFATCharSet)
{
delete pwszFATCharSet;
pwszFATCharSet = NULL;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: GetVirtualCtrNodeForTest
//
// Synopsis: Gets a random VirtualCtrNode for doing tests on it.
//
// Arguments: [pVirtualCtrNode] - Pointer to root node of subtree.
// [pgdi] - pointer to data generator object
// [cMin] - Minimum no of VirtualCtrNodes in subtree.
// Should be greater than zero and less than cMax.
// [cMax] - Maximum number of VirtualCtrNodes in subtree.
// Should be greater or equal to cMin
// [ppVirtualCtrNodeForTest] - Returned VirtualCtrNode
//
// Returns: HRESULT
//
// History: 27-Apr-96 NarindK Created.
// 12-Mar-97 MikeW Converted to use CtrNodes not VirtDF's
//
// Notes: If the number of actual maximum number of storages is known,
// provide that to cMax parameter or else pass 0 to have
// EnumerateInMemoryDocfile called for you to know actual number
// of storages (thereby VirtualCtrNodes) in the tree in test. Pl.
// note that if a test provides improper values for cMin/cMax,
// asserts would be thrown by the function. However it is okay to
// provide valid cMin and cMax values which are lesser than actual
// number of VirtualCtrNodes in the tree.
//
// Call OpenRandomVirtualCtrNodeStg after calling this function to
// open up the storage of this random VirtualCtrNode. This might
// not be required if the original VirtualDF tree is being used,
// since during first creation of VirtualDF tree, when all stgs/
// stms are created, they are open. However if a InMemory Docfile
// is generated from Disk DocFile, then only the root storage is
// open, all other storages/streams are closed.
//
// -Pick up a random number cRandom between cMin and cmax by
// DataGen obj pgdi.
// -Assign root VirtualCtrNode of tree to pvcnTrav and increment
// temp variable counter.
// -if counter is equal to cRandom i.e. 1, then return root Virtual
// CtrNode for test.
// -Else start a forever loop till node is found
// -While pvcnTrav's _pvcnChild is not NULL and counter is less
// than cRandom, loop.
// -if counter equals cRandom, then node found, break out of
// forever loop.
// -Else while pvcnTrav's _pvcnSister is eual to NULL, loop
// assinging _pvcnParent to pvcnTrav
// -Assign pvcnTrav's _pvcnSister to pvcnTrav and increment
// counter and go back to start of forever loop
// -With node found, return that to calling function.
//--------------------------------------------------------------------------
HRESULT GetVirtualCtrNodeForTest(
VirtualCtrNode *pVirtualCtrNode,
DG_INTEGER *pdgi,
ULONG cMin,
ULONG cMax,
VirtualCtrNode **ppVirtualCtrNodeForTest)
{
HRESULT hr = S_OK;
VirtualCtrNode *pvcnTrav = NULL;
USHORT usErr = 0;
ULONG counter = 0;
ULONG cRandom = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GetVirtualCtrNodeForTest"));
DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
DH_VDATEPTRIN(pVirtualCtrNode, VirtualCtrNode ) ;
DH_VDATEPTROUT(ppVirtualCtrNodeForTest, PVCTRNODE) ;
DH_ASSERT(NULL != pdgi);
DH_ASSERT(NULL != pVirtualCtrNode);
DH_ASSERT(NULL != ppVirtualCtrNodeForTest);
// Sanity check: The tree must have atleast one virtualCtrNode in it,
// and cMin must be <= cMax
DH_ASSERT(cMin > 0);
DH_ASSERT(cMin <= cMax || 0 == cMax);
// Initialize out parameter
*ppVirtualCtrNodeForTest = NULL;
// If cMax is 0, find the number of CtrNodes under the given root.
if (S_OK == hr && 0 == cMax)
{
hr = EnumerateInMemoryDocFile(pVirtualCtrNode, &cMax, NULL);
if (S_OK == hr && cMax < cMin)
{
hr = E_UNEXPECTED;
}
}
// Pick up a random number
if(S_OK == hr)
{
usErr = pdgi->Generate(&cRandom, cMin, cMax);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if(S_OK == hr)
{
pvcnTrav = pVirtualCtrNode;
// pvcnTrav = pVirtualDF->GetVirtualDFRoot();
// DH_ASSERT(NULL != pvcnTrav);
counter++;
if(counter != cRandom)
{
for(;;)
{
DH_ASSERT((NULL != pvcnTrav) && (cRandom >= counter));
while((pvcnTrav->GetFirstChildVirtualCtrNode() != NULL) &&
(counter < cRandom))
{
pvcnTrav = pvcnTrav->GetFirstChildVirtualCtrNode();
counter++;
}
if(cRandom == counter)
{
break;
}
while(NULL == pvcnTrav->GetFirstSisterVirtualCtrNode())
{
pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
DH_ASSERT(NULL != pvcnTrav);
}
DH_ASSERT(NULL != pvcnTrav->GetFirstSisterVirtualCtrNode());
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
counter++;
}
}
}
if(S_OK == hr)
{
// Return the out parameter
*ppVirtualCtrNodeForTest = pvcnTrav;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: GetVirtualCtrNodeForTest
//
// Synopsis: Gets a random VirtualCtrNode for doing tests on it.
//
// Arguments: [pVirtualDF] - Pointer to VirtualDF tree.
// [pgdi] - pointer to data generator object
// [cMin] - Minimum no of VirtualCtrNodes in subtree.
// Should be greater than zero and less than cMax.
// [cMax] - Maximum number of VirtualCtrNodes in subtree.
// Should be greater or equal to cMin
// [ppVirtualCtrNodeForTest] - Returned VirtualCtrNode
//
// Returns: HRESULT
//
// History: 12-Mar-97 MikeW Created
//
// Notes: Just thunk to the version of the routine that takes a
// VirtualCtrNode instead of a VirtualDF.
//--------------------------------------------------------------------------
HRESULT GetVirtualCtrNodeForTest(
VirtualDF *pVirtualDF,
DG_INTEGER *pdgi,
ULONG cMin,
ULONG cMax,
VirtualCtrNode **ppVirtualCtrNodeForTest)
{
DH_VDATEPTRIN(pVirtualDF, *pVirtualDF);
//
// Most of the parameter checking is left to the main version of this
// routine
//
return GetVirtualCtrNodeForTest(
pVirtualDF->GetVirtualDFRoot(),
pdgi,
cMin,
cMax,
ppVirtualCtrNodeForTest);
}
//+-------------------------------------------------------------------------
// Function: GetVirtualStmNodeForTest
//
// Synopsis: Gets a VirtualStmNode for doing tests on it.
//
// Arguments: [pVirtualCtrNode] - Pointer to root node of subtree.
// [pgdi] - pointer to data generator object
// [cMin] - Minimum no of VirtualStmNodes in VirtualDF tree.
// Should be greater than zero and less than cMax.
// [cMax] - Maximum number of VirtualStmNodes in VirtualDF tree.
// Should be greater or equal to cMin
// [ppVirtualCtrNodeParent] - returned parent VirtualCtrNode
// [ppVirtualStmNodeForTest] - returned VirtualStmNode
//
// Returns: HRESULT
//
// History: 27-Apr-96 NarindK Created.
// 12-Mar-97 MikeW Converted to use CtrNodes not VirtDF's
//
// Notes: If the number of actual maximum number of storages is known,
// provide that to cMax parameter or else pass 0 to have
// EnumerateInMemoryDocfile called for you to know actual number
// of storages (thereby VirtualCtrNodes) in the tree in test. Pl.
// note that if a test provides improper values for cMin/cMax,
// asserts would be thrown by the function. However it is okay to
// provide valid cMin and cMax values which are lesser than actual
// number of VirtualStmNodes in the tree.
//
// Also note that this function returns a randomly picked Virtual
// StmNode and its parent VirtualCtrNode (which is also randomly
// picked based on VirtualStmNode). The difference of this func
// from GetVirtualCtrNode is that the random VirtualCtrNode picked
// up is one having streams in it. If none of VirtualCtrNodes
// traversed have any streams in it, this returns an error.
//
// -Pick up a random number cRandomStm between cMin and cMax by
// DataGen obj pgdi.
// -Assign root VirtualCtrNode of tree to pvcnTrav and increment
// temp variable counter.
// -Check in pvcnTrav's _cStreams > 0, if yes, then increment the
// counter by that number.
// -if counter is greater or equal cRandom , check return tha
// desired VirtualStmNode of the root.
// -Else start a forever loop till a valid node is found
// -While pvcnTrav's _pvcnChild is not NULL and counter is less
// than cRandomStg, loop. In the loop, check if pvcnTrav's
// > 0, if yes, update the counter.
// -if counter is greater or equal to cRandomStg, then break
// out of the forever loop
// -Else while pvcnTrav's _pvcnSister is eual to NULL, loop
// assinging _pvcnParent to pvcnTrav
// -Assign pvcnTrav's _pvcnSister to pvcnTrav . If pvcnTrav's
// _cStreams is > 0, then update the counter and go back to
// start of forever loop
// -With parent VirtualCtrNode found, find the number of which
// child VirtualStmNode of it to return by doing cRandomStm
// minus (counter minus pvcnTrav's _cStreams count). Assign this
// calculated value to cChildStm.
// -Assign pvsnTrav the value of pvcnTrav's _pvsnStream and decre
// ment the cChildStm variable.
// -While cChildStm != zer0 and NULL is not equal to pvsnTrav,loop
// -Assign pvsnTrav's _pvsnSister to pvsnTrav.
// -Decrement cChildStm and go back to top of loop.
// -Return the parent VirtualCtrNode and random VirtualStmNode
// to the caller.
//--------------------------------------------------------------------------
HRESULT GetVirtualStmNodeForTest(
VirtualCtrNode *pVirtualCtrNode,
DG_INTEGER *pdgi,
ULONG cMin,
ULONG cMax,
VirtualCtrNode **ppVirtualCtrNodeParent,
VirtualStmNode **ppVirtualStmNodeForTest)
{
HRESULT hr = S_OK;
VirtualCtrNode *pvcnTrav = NULL;
VirtualStmNode *pvsnTrav = NULL;
USHORT usErr = 0;
ULONG counter = 0;
ULONG cRandomStm = 0;
ULONG cChildStm = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GetVirtualStmNodeForTest"));
DH_VDATEPTRIN(pVirtualCtrNode, VirtualCtrNode ) ;
DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
DH_VDATEPTROUT(ppVirtualStmNodeForTest, PVSTMNODE) ;
DH_VDATEPTROUT(ppVirtualCtrNodeParent, PVCTRNODE) ;
// The pointer to parent pVirtualCtrNodeParent shouldn't be NULL.
// cChildStmToFetch can be zero, in which case first stream is
// is returned.
DH_ASSERT(NULL != pdgi);
DH_ASSERT(NULL != pVirtualCtrNode);
DH_ASSERT(NULL != ppVirtualStmNodeForTest);
DH_ASSERT(NULL != ppVirtualCtrNodeParent);
// Sanity check: cMin must be <= cMax or cMax must be 0
DH_ASSERT(cMin <= cMax || 0 == cMax);
// if cMax is 0, find the number of stm nodes under the root
if(S_OK == hr && cMax == 0)
{
hr = EnumerateInMemoryDocFile(pVirtualCtrNode, NULL, &cMax);
if (S_OK == hr && cMax < cMin)
{
hr = E_UNEXPECTED;
}
}
// Pick up a random number
if(S_OK == hr)
{
// Initialize out parameter
*ppVirtualCtrNodeParent = NULL;
*ppVirtualStmNodeForTest = NULL;
usErr = pdgi->Generate(&cRandomStm, cMin, cMax);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if(S_OK == hr)
{
pvcnTrav = pVirtualCtrNode;
// pvcnTrav = pVirtualDF->GetVirtualDFRoot();
// DH_ASSERT(NULL != pvcnTrav);
if(0 != pvcnTrav->GetVirtualCtrNodeStreamCount())
{
counter = counter + pvcnTrav->GetVirtualCtrNodeStreamCount();
}
}
if(counter < cRandomStm)
{
for(;;)
{
DH_ASSERT(NULL != pvcnTrav);
while((pvcnTrav->GetFirstChildVirtualCtrNode() != NULL) &&
(counter < cRandomStm))
{
pvcnTrav = pvcnTrav->GetFirstChildVirtualCtrNode();
if(0 != pvcnTrav->GetVirtualCtrNodeStreamCount())
{
counter = counter + pvcnTrav->GetVirtualCtrNodeStreamCount();
}
}
if(counter >= cRandomStm)
{
break;
}
while(NULL == pvcnTrav->GetFirstSisterVirtualCtrNode())
{
pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
DH_ASSERT(NULL != pvcnTrav);
}
DH_ASSERT(NULL != pvcnTrav->GetFirstSisterVirtualCtrNode());
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
if(0 != pvcnTrav->GetVirtualCtrNodeStreamCount())
{
counter = counter + pvcnTrav->GetVirtualCtrNodeStreamCount();
}
}
}
if(S_OK == hr)
{
// Calculate which child stream needs to be picked up
cChildStm = cRandomStm -
(counter - pvcnTrav->GetVirtualCtrNodeStreamCount());
pvsnTrav = pvcnTrav->GetFirstChildVirtualStmNode();
cChildStm--;
DH_ASSERT(NULL != pvsnTrav);
while((0 != cChildStm) && (NULL != pvsnTrav))
{
pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode();
cChildStm--;
}
// Return the out parameter
*ppVirtualCtrNodeParent = pvcnTrav;
*ppVirtualStmNodeForTest = pvsnTrav;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: GetVirtualStmNodeForTest
//
// Synopsis: Gets a VirtualStmNode for doing tests on it.
//
// Arguments: [pVirtualDF] - Pointer to VirtualDF tree.
// [pgdi] - pointer to data generator object
// [cMin] - Minimum no of VirtualStmNodes in VirtualDF tree.
// Should be greater than zero and less than cMax.
// [cMax] - Maximum number of VirtualStmNodes in VirtualDF tree.
// Should be greater or equal to cMin
// [ppVirtualCtrNodeParent] - returned parent VirtualCtrNode
// [ppVirtualStmNodeForTest] - returned VirtualStmNode
//
// Returns: HRESULT
//
// History: 12-Mar-97 MikeW Created
//
// Notes: Just thunk to the version of the routine that takes a
// VirtualCtrNode instead of a VirtualDF.
//--------------------------------------------------------------------------
HRESULT GetVirtualStmNodeForTest(
VirtualDF *pVirtualDF,
DG_INTEGER *pdgi,
ULONG cMin,
ULONG cMax,
VirtualCtrNode **ppVirtualCtrNodeParent,
VirtualStmNode **ppVirtualStmNodeForTest)
{
DH_VDATEPTRIN(pVirtualDF, *pVirtualDF);
//
// Most of the parameter checking is left to the main version of this
// routine
//
return GetVirtualStmNodeForTest(
pVirtualDF->GetVirtualDFRoot(),
pdgi,
cMin,
cMax,
ppVirtualCtrNodeParent,
ppVirtualStmNodeForTest);
}
//+-------------------------------------------------------------------------
// Function: DestroyStorage
//
// Synopsis: Destorys a VirtualCtrNode and associated IStorage.
//
// Arguments: [pVirtualDF] - pointer to VirtualDocFile tree.
// [pVirtualCtrNode] - Pointer to VirtualCtrNode
//
// Returns: HRESULT
//
// History: 29-Apr-96 NarindK Created.
//
// Notes: Call VirtualCtrNode::Destroy to destroy the node.
// Call VirtualDF::DeleteVirtualDocFileTree to delete the corres-
// ponding VirtualCtrNode from the VirtualDF tree.
//--------------------------------------------------------------------------
HRESULT DestroyStorage(
VirtualDF *pVirtualDF,
VirtualCtrNode *pVirtualCtrNode)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("DestroyStorage"));
DH_VDATEPTRIN(pVirtualDF, VirtualDF) ;
DH_VDATEPTRIN(pVirtualCtrNode, VirtualCtrNode) ;
DH_ASSERT(NULL != pVirtualCtrNode);
DH_ASSERT(NULL != pVirtualDF);
if(S_OK == hr)
{
hr = pVirtualCtrNode->Destroy();
DH_HRCHECK(hr, TEXT("pVirtualCtrNode->Destroy()")) ;
}
if(S_OK == hr)
{
// Now adjust the VirtualDocFile tree. This will decrease the
// _cChildren variable value of the parent VrtualCtrNode too.
hr = pVirtualDF->DeleteVirtualDocFileTree(pVirtualCtrNode);
DH_HRCHECK(hr, TEXT("pTestVirtualDF->DeleteVirtualFileDocTree")) ;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: DestroyStream
//
// Synopsis: Destorys a VirtualStmNode and associated IStream.
//
// Arguments: [pVirtualDF] - pointer to VirtualDF tree
// [pVirtualStmNode] - Pointer to VirtualStmNode to be destoryed
//
// Returns: HRESULT
//
// History: 9-July-96 NarindK Created.
//
// Notes: Call VirtualStmNode::Destroy to destroy the IStream.
// Call VirtualDF::DeleteVirtualCtrNodeStreamNode to delete corres-
// ponding VirtualCtrNode from the VirtualDF tree.
//--------------------------------------------------------------------------
HRESULT DestroyStream(
VirtualDF *pVirtualDF,
VirtualStmNode *pVirtualStmNode)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("DestroyStream"));
DH_VDATEPTRIN(pVirtualStmNode, VirtualStmNode) ;
DH_VDATEPTRIN(pVirtualDF, VirtualDF) ;
DH_ASSERT(NULL != pVirtualDF);
DH_ASSERT(NULL != pVirtualStmNode);
if(S_OK == hr)
{
hr = pVirtualStmNode->Destroy();
DH_HRCHECK(hr, TEXT("pVirtualStmNode->Destroy()")) ;
}
if(S_OK == hr)
{
// Now adjust the VirtualDocFile tree. This will decrease the
// _cStreams variable value of the parent VirtualCtrNode too.
hr = pVirtualDF->DeleteVirtualCtrNodeStreamNode(pVirtualStmNode);
DH_HRCHECK(hr, TEXT("pTestVirtualDF->DeleteVirtualCtrNodeStreamNode")) ;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: AddStorage
//
// Synopsis: Adds a VirtualCtrNode and associated IStorage.
//
// Arguments: [pVirtualCtrNode] - Pointer to existing VirtualCtrNode
// [ppNewVirtualCtrNode] _ Returned new VirtualCtrNode
// [pName] - Name of new storage
// [grfMode] - Mode in which new storage is to be opened
//
// Returns: HRESULT
//
// History: 29-Apr-96 NarindK Created.
//
// Notes: - Creates a simple new VirtualCtrNode and initializes it with
// name passed in. Its _cChildren and _cStreams are initialized
// to zero.
// - Append the newly created node pvcnNew to its parent node
// pVirtualCtrNode. This would be appended as _pvcnChild or
// as _pvcnSister of existing old sister as the case might be.
// - Increase the parent's pVirtualCtrNode's _cChildren variable
// indicating the new VirtualCtrNode added.
// - Create a disk IStorage corresponding to this VirtualCtrNode
// based on passed in grfmode.
// - If CreateStorage call returns STG_S_CONVERTED, it indicates
// that an existing stream with specified name was replaced witho
// a new storage object containing a single stream called
// CONTENTS. If so, adjust the VirtualDF tree.
// - If successful, copy pvcnNew into out parameter *ppNewVirtual
// CtrNode, else delete the VirtualCtrNode allocated earlier.
// Note: Please note that the CRC for node(s) created is not set.
//--------------------------------------------------------------------------
HRESULT AddStorage(
VirtualDF *pVirtualDF,
VirtualCtrNode *pVirtualCtrNode,
LPTSTR pName,
DWORD grfMode,
VirtualCtrNode **ppNewVirtualCtrNode)
{
HRESULT hr = S_OK;
HRESULT hrTemp = S_OK;
VirtualCtrNode *pvcnNew = NULL;
VirtualStmNode *pvsnOld = NULL;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::AddStorage"));
DH_VDATEPTRIN(pVirtualDF, VirtualDF) ;
DH_VDATEPTRIN(pVirtualCtrNode, VirtualCtrNode) ;
DH_VDATEPTROUT(ppNewVirtualCtrNode, PVCTRNODE) ;
DH_VDATESTRINGPTR(pName);
DH_ASSERT(NULL != pVirtualDF);
DH_ASSERT(NULL != pVirtualCtrNode);
DH_ASSERT(NULL != ppNewVirtualCtrNode);
if(S_OK == hr)
{
// Initialize out parameter
*ppNewVirtualCtrNode = NULL;
// Allocate and Initialize new VirtualCtrNode
hr = GenVirtualCtrNode(pName, &pvcnNew);
DH_HRCHECK(hr, TEXT("GenVirtualCtrNode")) ;
}
// Append new VirtualCtr Node
if(S_OK == hr)
{
if(0 == pVirtualCtrNode->GetVirtualCtrNodeChildrenCount())
{
hr = pVirtualCtrNode->AppendChildCtr(pvcnNew);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendChildCtr")) ;
}
else
{
hr=pVirtualCtrNode->GetFirstChildVirtualCtrNode()->AppendSisterCtr(
pvcnNew);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendSisterCtr")) ;
}
}
if(S_OK == hr)
{
// Increment the _cChildren variable of parent VirtualCtrNode
pVirtualCtrNode->IncreaseChildrenStgCount();
}
// Call VirtualCtrNode::Create to create a corresponding Storage on disk.
if(S_OK == hr)
{
hr = pvcnNew->Create(
grfMode,
0,
0);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Create")) ;
}
// Fill in the output parameter
if((S_OK == hr) || (STG_S_CONVERTED == hr))
{
if(STG_S_CONVERTED == hr)
{
VirtualStmNode *pvsnNew = NULL;
ULONG cb = 0;
// Remember hr
hrTemp = hr;
// Delete the VirtualStmNode with stream that is converted to this
// storage. First find the corresponding VirtualStmNode with same
// name.
pvsnOld =
pvcnNew->GetParentVirtualCtrNode()->GetFirstChildVirtualStmNode();
DH_ASSERT(NULL != pvsnOld);
while((NULL != pvsnOld) &&
(0 != _tcscmp(pName, pvsnOld->GetVirtualStmNodeName())))
{
pvsnOld = pvsnOld->GetFirstSisterVirtualStmNode();
}
// Delete the old VirtualStmNode
if((NULL != pvsnOld) &&
(0 == _tcscmp(pName, pvsnOld->GetVirtualStmNodeName())))
{
// Remember size of VirtualStmNode
cb = pvsnOld->GetVirtualStmNodeSize();
hr = pVirtualDF->DeleteVirtualCtrNodeStreamNode(pvsnOld);
}
else
{
hr = E_FAIL;
}
// Generate a new VirtualStmNode for CONTENTS stream generated
if(S_OK == hr)
{
hr = GenVirtualStmNode(TEXT("CONTENTS"), cb, &pvsnNew);
if(S_OK == hr)
{
hr = pvcnNew->AppendFirstChildStm(pvsnNew);
}
if(S_OK == hr)
{
pvcnNew->IncreaseChildrenStmCount();
}
}
}
if(S_OK == hr)
{
*ppNewVirtualCtrNode = pvcnNew;
if(STG_S_CONVERTED == hrTemp)
{
hr = hrTemp;
}
}
}
else
{
// Storage wasn't created successfully, delete the VirtualCtrNode
// being created. Adjust the VirtualDocFile tree. This will decrease
// _cChildren variable value of the parent VirtualCtrNode too.
hrTemp = pVirtualDF->DeleteVirtualDocFileTree(pvcnNew);
DH_HRCHECK(hrTemp, TEXT("pVirtualDF->DeleteVirtualFileDocTree")) ;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: AddStream
//
// Synopsis: Adds a VirtualStmNode & associated IStream to a VirtualCtrNode.
// Set the size of stream if cbSize is nonzero, but doesn't write
// into it.
//
// Arguments: [pVirtualCtrNode] - Pointer to existing VirtualCtrNode
// [ppNewVirtualStmNode] - Returned new VirtualStmNode
// [pName] - Name of new stream
// [grfMode] - Mode of new stream
// [cbSize] - Size of new stream
//
// Returns: HRESULT
//
// History: 29-Apr-96 NarindK Created.
//
// Notes: - Creates a simple new VirtualStmNode and initializes it with
// name & cbSize passed in.
// - Append the newly created node pvsnNew to its parent node
// pVirtualCtrNode. This would be appended as _pvsnStream or
// as _pvsnSister of existing old sister as the case might be.
// - Increase the parent's pVirtualCtrNode's _cStreams variable
// indicating the new VirtualStmNode added.
// - Create a disk IStream corresponding to this VirtualStmNode.
// based on passed in grfmode.
// - If cbSize is non zero, do SetSize on stream.
// - If successful, copy pvsnNew into out parameter *ppNewVirtual
// StmNode, else delete the VirtualStmNode allocated earlier.
// Note: Please note that the CRC for node created is not set.
//--------------------------------------------------------------------------
HRESULT AddStream(
VirtualDF *pVirtualDF,
VirtualCtrNode *pVirtualCtrNode,
LPTSTR pName,
ULONG cbSize,
DWORD grfMode,
VirtualStmNode **ppNewVirtualStmNode)
{
HRESULT hr = S_OK;
HRESULT hrTemp = S_OK;
VirtualStmNode *pvsnNew = NULL;
ULARGE_INTEGER uli;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::AddStream"));
DH_VDATEPTRIN(pVirtualDF, VirtualDF) ;
DH_VDATEPTRIN(pVirtualCtrNode, VirtualCtrNode) ;
DH_VDATEPTROUT(ppNewVirtualStmNode, PVSTMNODE) ;
DH_VDATESTRINGPTR(pName);
DH_ASSERT(NULL != pVirtualCtrNode);
DH_ASSERT(NULL != ppNewVirtualStmNode);
if(S_OK == hr)
{
// Initialize out parameter
*ppNewVirtualStmNode = NULL;
// Allocate and Initialize new VirtualStmNode
hr = GenVirtualStmNode(pName, cbSize, &pvsnNew);
DH_HRCHECK(hr, TEXT("GenVirtualStmNode")) ;
}
// Append new VirtualStm Node
if(S_OK == hr)
{
if(0 == pVirtualCtrNode->GetVirtualCtrNodeStreamCount())
{
hr = pVirtualCtrNode->AppendFirstChildStm(pvsnNew);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendFirstChildStm")) ;
}
else
{
hr=pVirtualCtrNode->GetFirstChildVirtualStmNode()->AppendSisterStm(
pvsnNew);
DH_HRCHECK(hr, TEXT("VirtualStmNode::AppendSisterStm")) ;
}
}
if(S_OK == hr)
{
// Increment the _cStreams variable of parent VirtualCtrNode
pVirtualCtrNode->IncreaseChildrenStmCount();
}
// Call VirtualStmNode::Create to create a corresponding Stream on disk.
if(S_OK == hr)
{
hr = pvsnNew->Create(
grfMode,
0,
0);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Create")) ;
}
// Call VirtualStmNode::SetSize to set size of stream.
if((S_OK == hr) && (0 != cbSize))
{
ULISet32(uli, cbSize);
hr = pvsnNew->SetSize(uli);
DH_HRCHECK(hr, TEXT("VirtualStmNode::SetSize")) ;
}
// Fill in the output parameter
if(S_OK == hr)
{
*ppNewVirtualStmNode = pvsnNew;
}
else
{
// Stream wasn't created successfully, so delete the VirtualStmNode.
// Adjust the VirtualDocFile tree. This will decrease the
// _cStreams variable value of the parent VirtualCtrNode too.
hrTemp = pVirtualDF->DeleteVirtualCtrNodeStreamNode(pvsnNew);
DH_HRCHECK(
hrTemp,
TEXT("pVirtualDF->DeleteVirtualCtrNodeStreamNode")) ;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: CalculateCRCForName
//
// Synopsis: Calulates CRC for a IStorage/IStream's name.
//
// Arguments: [ptcsName] - pointer to name of stream
// [pdwCRCForName] - pointer to CRC
//
// Returns: HRESULT
//
// History: 8-May-96 NarindK Created.
//
// Notes: This is a common function used by other CRC utilities function
// and also called directly is virtdf.cxx to calculate in memory
// CRC for VirtualCtrNode. Since for VirtualCtrNodes/IStorages,
// we CRC only name, we could use this function to calculate CRC.
// - Assign passed in name to a temp. variable ptszTemp.
// - Loop while *ptszTemp is not NULL, and call CRC_CALC macro
// to generate CRC for the name.
//--------------------------------------------------------------------------
HRESULT CalculateCRCForName(
const LPTSTR ptcsName,
DWORD *pdwCRCForName)
{
HRESULT hr = S_OK;
LPTSTR ptszTemp = NULL;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CalculateCRCForName"));
DH_VDATESTRINGPTR(ptcsName) ;
DH_VDATEPTROUT(pdwCRCForName, DWORD) ;
DH_ASSERT(NULL != ptcsName);
DH_ASSERT(NULL != pdwCRCForName);
if(S_OK == hr)
{
// Initialize out parameter
*pdwCRCForName = CRC_PRECONDITION;
ptszTemp = ptcsName;
while(NULL != *ptszTemp)
{
CRC_CALC(*pdwCRCForName, (BYTE)*ptszTemp++);
}
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: CalculateCRCForDataBuffer
//
// Synopsis: Calulates CRC for a given data Buffer.
//
// Arguments: [ptszBuffer] - pointer to data buffer.
// [culBufferSize] - size of data buffer
// [pdwCRCForName] - pointer to CRC
//
// Returns: HRESULT
//
// History: 8-May-96 NarindK Created.
//
// Notes: This is a common function used by other CRC utilities function
// - Assign pointer to passed in buffer to pByteBuffer.
// - Loop for culBufferSize, and call CRC_CALC macro
// to generate CRC for the data buffer.
//--------------------------------------------------------------------------
HRESULT CalculateCRCForDataBuffer(
const LPTSTR ptszBuffer,
ULONG culBufferSize,
DWORD *pdwCRCForDataBuffer)
{
HRESULT hr = S_OK;
LPBYTE pByteBuffer = NULL;
ULONG i = 0;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CalculateCRCForDataBuffer"));
DH_VDATEPTRIN(ptszBuffer, TCHAR);
DH_VDATEPTROUT(pdwCRCForDataBuffer, DWORD) ;
DH_ASSERT(NULL != ptszBuffer);
DH_ASSERT(NULL != pdwCRCForDataBuffer);
// calculate the CRC for data of stream.
if(S_OK == hr)
{
// Initialize out parameter
*pdwCRCForDataBuffer = CRC_PRECONDITION;
pByteBuffer = (BYTE *)ptszBuffer;
if ( S_OK == hr )
{
for (i=0; i < culBufferSize; i++)
{
CRC_CALC(*pdwCRCForDataBuffer, pByteBuffer[i]);
}
}
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: CalculateInMemoryCRCForStg
//
// Synopsis: Calulate in memory CRC for a Stroage name
//
// Arguments: [pvsn] - Pointer to VirtualCtrNode.
// [pdwCRC] - pointer to computed CRC
//
// Returns: HRESULT
//
// History: 8-May-96 NarindK Created.
//
// Notes: For IStorages, only name is CRC'd.
// - Call CalculateCRCForName to calculate CRC
//
//--------------------------------------------------------------------------
HRESULT CalculateInMemoryCRCForStg(
VirtualCtrNode *pvcn,
DWORD *pdwCRC)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB,_TEXT("CalculateInMemoryCRCForStg"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
DH_VDATEPTROUT(pdwCRC, DWORD) ;
DH_ASSERT(NULL != pvcn);
DH_ASSERT(NULL != pdwCRC);
// Now calulate the CRC for name of storage.
if ( S_OK == hr )
{
// Initialize out parameter
*pdwCRC = CRC_PRECONDITION;
hr = CalculateCRCForName(pvcn->GetVirtualCtrNodeName(), pdwCRC);
DH_HRCHECK(hr, TEXT("CalculateCRCForName")) ;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: CalculateInMemoryCRCForStm
//
// Synopsis: Calulates CRC for a IStream's data and name.
//
// Arguments: [pvsn] - Pointer to VirtualStmNode.
// [ptszBuffer] - Pointer to buffer used to write into stream
// [culBufferSize] - Pointer to buffer size used to calculate CRC
// [pdwCRC] - pointer to computed CRC
//
// Returns: HRESULT
//
// History: 8-May-96 NarindK Created.
//
// Notes: For IStreams, both name and data of stream are CRC'd. Ensure
// that stream is opened before this function is called.
//
// This function is presently called directly in virtdf.cxx to
// calculate in memory CRC for VirtualStmNode. Since for the
// VirtualStmNodes/IStreams, we CRC name and data, we could use
// this function to calculate CRC if we pass it the stream name,
// buffer, size of buffer as input parameters.
// - Call CalculateCRCForDataBuffer to calculate dwCRCForData.
// - Call CalculateCRCForName to calculate dwCRCForName.
// - Compute the total CRC based on above two CRC's.
//
//--------------------------------------------------------------------------
HRESULT CalculateInMemoryCRCForStm(
VirtualStmNode *pvsn,
const LPTSTR ptszBuffer,
ULONG culBufferSize,
DWCRCSTM *pdwCRC)
{
HRESULT hr = S_OK;
DWORD dwCRCForData= CRC_PRECONDITION;
DWORD dwCRCForName= CRC_PRECONDITION;
ULONG i = 0;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB,_TEXT("CalculateInMemoryCRCForStm"));
DH_VDATEPTRIN(pvsn, VirtualStmNode) ;
DH_VDATEPTROUT(pdwCRC, DWORD) ;
DH_VDATEPTRIN(ptszBuffer, TCHAR);
DH_ASSERT(NULL != pvsn);
DH_ASSERT(NULL != ptszBuffer);
DH_ASSERT(NULL != pdwCRC);
if(S_OK == hr)
{
// Initialize CRC values to CRC_PRECONDITION
pdwCRC->dwCRCName = pdwCRC->dwCRCData = pdwCRC->dwCRCSum = CRC_PRECONDITION;
}
// First calculate the CRC for data of stream.
if(S_OK == hr)
{
hr = CalculateCRCForDataBuffer(ptszBuffer, culBufferSize,&dwCRCForData);
DH_HRCHECK(hr, TEXT("CalculateCRCForDataBuffer")) ;
}
// Now calulate the CRC for name of stream.
if ( S_OK == hr )
{
hr = CalculateCRCForName(pvsn->GetVirtualStmNodeName(), &dwCRCForName);
DH_HRCHECK(hr, TEXT("CalculateCRCForName")) ;
}
// Compute the total CRC value based on above two CRC's and record
// individual CRC's for name and data
if ( S_OK == hr )
{
pdwCRC->dwCRCData = dwCRCForData;
pdwCRC->dwCRCName = dwCRCForName;
MUNGECRC(pdwCRC->dwCRCSum,dwCRCForData);
MUNGECRC(pdwCRC->dwCRCSum,dwCRCForName);
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: CalculateStreamDataCRC
//
// Synopsis: Calculates the CRC of the stream data,
// using the IStream given (independent of virtualdf stuff)
//
// Arguments: [pStm] - the Stream
// [dwSize] - the size if known, or zero => call Stat
// [pdwCRC] - pointer to data CRC
// [dwChunkSize] - if >0 the stream will be read at chunks
// of this size.
//
// Returns: HRESULT
//
// History: 02-Apr-98 georgis Created.
//
//--------------------------------------------------------------------------
HRESULT CalculateStreamDataCRC(IStream *pStm,
DWORD dwSize,
DWORD *pdwCRC,
DWORD dwChunkSize)
{
HRESULT hr=S_OK;
STATSTG statstg;
DWORD dwBufferSize=0;
BYTE *pBuffer=NULL;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CalculateStreamDataCRC"));
DH_VDATEPTRIN(pStm, IStream);
DH_VDATEPTROUT(pdwCRC, DWORD);
*pdwCRC=0; // invalid CRC
// Ask for size if unknown (zero passed)
if (0==dwSize)
{
hr = pStm->Stat(&statstg, STATFLAG_NONAME);
DH_HRCHECK(hr, TEXT("IStorage::Stat"));
dwSize=statstg.cbSize.LowPart; //BIGBUG: assume LowPart only
}
// Allocate the buffer
if (S_OK == hr)
{
if (dwChunkSize>0)
{
dwBufferSize=dwChunkSize;
}
else
{
dwBufferSize=dwSize;
}
pBuffer = new BYTE[dwBufferSize];
if (NULL==pBuffer)
{
hr=E_OUTOFMEMORY;
DH_HRCHECK(hr,TEXT("new"));
}
}
// Reset the stream
if (S_OK== hr)
{
LARGE_INTEGER li;
LISet32(li,0L);
hr=pStm->Seek(li,STREAM_SEEK_SET,NULL);
DH_HRCHECK(hr,TEXT("Seek"));
};
// Do the actual read, calculate the CRC
if (S_OK == hr)
{
DWORD dwTotalRead=0;
DWORD dwRead=0;
register DWORD dwCRC=CRC_PRECONDITION;
while ((S_OK==hr)&&(dwTotalRead < dwSize))
{
hr=pStm->Read(pBuffer, dwBufferSize, &dwRead);
DH_HRCHECK(hr,TEXT("Read"));
dwTotalRead+=dwRead;
if (S_OK==hr)
{
for (register int i=0; i<dwRead; i++)
{
CRC_CALC(dwCRC,pBuffer[i]);
}
};
}
*pdwCRC=dwCRC;
}
if (NULL!=pBuffer)
{
delete pBuffer;
};
return hr;
}
//+-------------------------------------------------------------------------
// Function: ReadAndCalculateDiskCRCForStm
//
// Synopsis: Calulates CRC for a IStream's name and data.
//
// Arguments: [pvsn] - pointer to VirtualStmNode
// [pdwCRC] - pointer to CRC
//
// Returns: HRESULT
//
// History: 8-May-96 NarindK Created.
// 2-Apr-98 georgis use VirtualStmNode::UpdateCRC
//
// Notes: VirtualStmNode::UpdateCRC() actually obsoletes this function,
// It remains for compatibility with the old tests
//
// BUGBUG: all the DWCRCSTM structures are called dw* and
// all pointers to them pdw* . We should fix this
//
//--------------------------------------------------------------------------
HRESULT ReadAndCalculateDiskCRCForStm(
VirtualStmNode *pvsn,
DWCRCSTM *pdwCRC,
DWORD dwChunkSize)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ReadAndCalculateDiskCRCForStm"));
DH_VDATEPTRIN(pvsn, VirtualStmNode) ;
DH_VDATEPTROUT(pdwCRC, DWCRCSTM) ;
hr=pvsn->UpdateCRC(dwChunkSize);
DH_HRCHECK(hr, TEXT("pvsn->UpdateCRC")) ;
pdwCRC->dwCRCSum =pvsn->GetVirtualStmNodeCRC();
pdwCRC->dwCRCName=pvsn->GetVirtualStmNodeCRCName();
pdwCRC->dwCRCData=pvsn->GetVirtualStmNodeCRCData();
return hr;
}
//+-------------------------------------------------------------------------
// Function: CalculateDiskCRCForStg
//
// Synopsis: Calulates CRC for a IStrorage's name.
//
// Arguments: [pvcn] - pointer to VirtualCtrNode
// [pdwCRCForName] - pointer to CRC
//
// Returns: HRESULT
//
// History: 8-May-96 NarindK Created.
//
// Notes: For IStorages, only name is CRC'd.
// -Call VirtualCtrNode::Stat to get information about storage.
// -Call CalculateCRCForName to calculate CRC for name of the
// storage obtained from STATSTG structure.
//--------------------------------------------------------------------------
HRESULT CalculateDiskCRCForStg(
VirtualCtrNode *pvcn,
DWORD *pdwCRCForName)
{
HRESULT hr = S_OK;
LPMALLOC pMalloc = NULL;
LPTSTR ptszName = NULL;
STATSTG statStg;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CalculateDiskCRCForStg"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
DH_VDATEPTROUT(pdwCRCForName, DWORD) ;
// For IStorages, only name are CRC'd.
DH_ASSERT(NULL != pvcn);
DH_ASSERT(NULL != pdwCRCForName);
// Initialization
statStg.pwcsName = NULL;
// Get the statistics about ths opened stream
if(S_OK == hr)
{
// Initialize out parameter
*pdwCRCForName = CRC_PRECONDITION;
hr = pvcn->Stat(&statStg, STATFLAG_DEFAULT);
DH_HRCHECK(hr, TEXT("IStorage::Stat")) ;
}
// First get pMalloc that would be used to free up the name string from
// STATSTG.
if ( S_OK == hr )
{
hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
}
if(S_OK == hr)
{
//Convert WCHAR to TCHAR
hr = OleStringToTString(statStg.pwcsName, &ptszName);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
}
if((S_OK == hr) && (NULL != ptszName))
{
hr = CalculateCRCForName(ptszName, pdwCRCForName);
DH_HRCHECK(hr, TEXT("CalculateCRCForName")) ;
}
// Clean up
if ( NULL != statStg.pwcsName)
{
pMalloc->Free(statStg.pwcsName);
statStg.pwcsName = NULL;
}
if(NULL != pMalloc)
{
pMalloc->Release();
pMalloc = NULL;
}
if(NULL != ptszName)
{
delete ptszName;
ptszName = NULL;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: EnumerateInMemoryDocFile
//
// Synopsis: Enumerates a in memory docfile.
//
// Arguments: [pvcn] - pointer to VirtualCtrNode
// [pdwNumStg] - pointer to number of Storages in doc hierarchy.
// [pdwNumStm] - pointer to number of streams in doc hierarchy
//
// Returns: HRESULT
//
// History: 3-June-96 NarindK Created.
//
// Notes: pdwNumStg, pdwNumStm may be NULL if user is not interested in
// these values to be returned back. Includes the passed in pvcn
// in pdwnumStg count.
// -Count the passed in storage pvcn as 1 in pNumStg count.
// -Check if pvcn's _pvsnStream is NULL or not by calling the
// GetFirstChildVirtualStmNode() function, assign to pvsnTrav var
// -If it is not NULL,loop till pvsnTrav is not NULL.
// -Increment pNumStm for stream found for this pvcn.
// -Assign pvcnTrav->_pvsnSister (GetFirstSisterVirtualStmNode)
// to pvsnTrav.
// -Go back to top of loop and repeat.
// -Check if pvcn's _pvcnChild is NULL or not by calling the func
// pvcn->GetFirstChildVirtualCtrNode() and assign it to pvcnTrav.
// -Loop while pvcnTrav is not NULL and hr is S_OK.
// -Make a recursive call to self (EnumerateInMemoryDocFile)
// -Assign pvcnTrav->_pvcnSister to pvcnTrav. (Got thru'
// GetFirstSisterVirtualCtrNode function).
// -Update pNumStg and pNumStm based on above call, where out
// parameters are cChildStg and cChildStm.
// -Reinitialize these variables and go back to top of loop.
//--------------------------------------------------------------------------
HRESULT EnumerateInMemoryDocFile(
VirtualCtrNode *pvcn,
ULONG *pNumStg,
ULONG *pNumStm )
{
HRESULT hr = S_OK;
ULONG cChildStg = 0;
ULONG cChildStm = 0;
VirtualCtrNode *pvcnTrav = NULL;
VirtualStmNode *pvsnTrav = NULL;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("EnumerateInMemoryDocFile"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
if(NULL != pNumStg)
{
DH_VDATEPTROUT(pNumStg, ULONG) ;
}
if(NULL != pNumStm)
{
DH_VDATEPTROUT(pNumStm, ULONG) ;
}
DH_ASSERT(NULL != pvcn);
if(S_OK == hr)
{
if(NULL != pNumStg)
{
// Count the storage passed in.
*pNumStg = 1;
}
if(NULL != pNumStm)
{
*pNumStm = 0;
}
pvsnTrav = pvcn->GetFirstChildVirtualStmNode();
// Count number of VirtualStmNodes that this VirtualCtrNode has.
while(NULL != pvsnTrav)
{
if(NULL != pNumStm)
{
(*pNumStm)++;
}
pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode();
}
// Next recurse into the child VirtualCtrNodes of this VirtualCtrNode
pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
while((NULL != pvcnTrav) && (S_OK == hr))
{
hr = EnumerateInMemoryDocFile(
pvcnTrav,
&cChildStg,
&cChildStm);
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
// Update number of nodes on basis of child nodes as found
if((NULL != pNumStg) && (0 != cChildStg))
{
*pNumStg = *pNumStg + cChildStg;
}
if((NULL != pNumStm) && (0 != cChildStm))
{
*pNumStm = *pNumStm + cChildStm;
}
// Reinitialize variables
cChildStg = 0;
cChildStm = 0;
}
}
// flatfile only: if we're at the root, increment stream counter to include
// the default flatfile stream (CONTENTS)
if(StorageIsFlat() && NULL == pvcn->GetParentVirtualCtrNode())
{
(*pNumStm)++;
}
return hr;
}
//-------------------------------------------------------------------------
// Function: OpenRandomVirtualCtrNodeStg
//
// Synopsis: Opens a VirtualCtrNode's IStorage. This traverses through all
// the parents of the VirtualCtrNode and opens them and then
// opens up the required storage. Please ensure that root IStorage
// is open before this call.
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode whose IStorage has to
// opened.
// [grfMode] - Mode to open the IStorage. (Note: all the parent
// IStorages would be opened in that mode too.)
//
// Returns: HRESULT
//
// History: 6-June-96 NarindK Created.
//
// Notes: This function doesn't reopen the root, which is already
// open since we need to have a valid function. If VirtualCtrNode // node whose storage has to be opened is same as Root, then
// functions returns w/o any error. Call CloseRandomVirtualCtr
// NodeStg function to close the storages opened by this call.
//
// -Initilize the counter to 1.
// -Assign pvcn to pvcnTrav and loop till pvcnTrav->_pvcnParent
// (obtained thru GetParentVirtualCtrNode() is non NULL)
// -Increment counter.
// -Assign pvcnTrav->_pvcnParent to pvcnTrav
// -Go back to top of loop and repeat.
// -Check if counter is 1 or not. If 1, then the node to be opened// is the root itsef that was opened prior to this call. So just
// return without any error.
// -If counter>1, then allocate an array of VirtualCtrNode pointers
// of size counter and continue.
// -Assign passed in node ovcn to temp var pvcnTrav. And fill up
// the above allocated arrays starting from the passed in node
// way upto root.
// -Increment the conter since root is already open, then in a
// do-while loop, open up all the nodes till we reach the passed
// in node. Pl. note that the nodes are opened as per grfMode that
// was passed in to us.
// -Delete the array of pointers.
//--------------------------------------------------------------------------
HRESULT OpenRandomVirtualCtrNodeStg(
VirtualCtrNode *pvcn,
DWORD grfMode)
{
HRESULT hr = S_OK;
ULONG counter = 1;
VirtualCtrNode *pvcnTrav = NULL;
PVCTRNODE *pvcnArrayPtr = NULL;
BOOL fIsRoot = FALSE;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("OpenRandomVirtualCtrNodeStg"));
DH_VDATEPTRIN(pvcn, PVCTRNODE) ;
DH_ASSERT(NULL != pvcn);
if(S_OK == hr)
{
// Count number of parents till the root.
pvcnTrav = pvcn;
while(NULL != pvcnTrav->GetParentVirtualCtrNode())
{
counter++;
pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
}
if( 1 == counter)
{
fIsRoot = TRUE;
}
else
{
// Allocate an array of desired size
pvcnArrayPtr = new PVCTRNODE [counter];
if(NULL == pvcnArrayPtr)
{
hr = E_OUTOFMEMORY;
}
}
}
if((S_OK == hr) && (FALSE == fIsRoot))
{
// Fill up the array starting from node itself, with parent chain
// upto including root.
pvcnTrav = pvcn;
pvcnArrayPtr[--counter] = pvcn;
while(NULL != pvcnTrav->GetParentVirtualCtrNode())
{
pvcnArrayPtr[--counter] = pvcnTrav->GetParentVirtualCtrNode();
pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
}
// Root is already open, so open the other parent nodes down to random
// test node.
counter++;
do
{
if(NULL != pvcnArrayPtr[counter]->GetIStoragePointer())
{
// If the storage is already open, then do an addref on it
// rather than trying to open it since all internal storages
// are always opened with STGM_SHARE_EXCLUSIVE mode (OLE).
hr = pvcnArrayPtr[counter]->AddRefCount();
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AddRefCount")) ;
}
else
{
hr = pvcnArrayPtr[counter]->Open(
NULL,
grfMode,
NULL,
0);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Open")) ;
}
} while(pvcnArrayPtr[counter++] != pvcn);
}
// Cleanup
if(NULL != pvcnArrayPtr)
{
delete []pvcnArrayPtr;
pvcnArrayPtr = NULL;
}
return hr;
}
//-------------------------------------------------------------------------
// Function: CloseRandomVirtualCtrNodeStg
//
// Synopsis: Close a VirtualCtrNode's IStorage and all other IStorages that
// were open in prior call to OpenRandomVirtualCtrNodeStg.
// This traverses through all the parents of the VirtualCtrNode
// and closes them excluding the root IStorage, which was not
// reopened during OpenRandomVirtualCtrNodeStg call.
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode whose IStorage has to
// closed.
//
// Returns: HRESULT
//
// History: 18-June-96 NarindK Created.
//
// Notes:
//--------------------------------------------------------------------------
HRESULT CloseRandomVirtualCtrNodeStg(VirtualCtrNode *pvcn)
{
HRESULT hr = S_OK;
VirtualCtrNode *pvcnTrav = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("CloseRandomVirtualCtrNodeStg"));
DH_VDATEPTRIN(pvcn, PVCTRNODE) ;
DH_ASSERT(NULL != pvcn);
pvcnTrav = pvcn;
if(S_OK == hr)
{
while((NULL != pvcnTrav->GetParentVirtualCtrNode()) && (S_OK == hr))
{
hr = pvcnTrav->Close();
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Close")) ;
pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
}
}
return hr;
}
//-------------------------------------------------------------------------
// Function: ParseVirtualDFAndCloseOpenStgsStms
//
// Synopsis: This function parses the VirtualDF tree and calls Close
// release on all open IStorages/IStreams pointers under and/
// or including the passed in VirtualCtrNode
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode
// [eNodeOp]- May be NODE_INC_TOPSTG / NODE_EXC_TOPSTG
//
// Returns: HRESULT
//
// History: 16-July-96 NarindK Created.
//
// Notes: If NODE_INC_TOPSTG is given, it calls a close/release on the
// passed in VirtualCtrNode, if it is NODE_EXC_TOPSTG, it doesn't
// call a close/release on the IStorage pointer of passed in
// VirtualCtrNode.
//
// Also note that if a Parent's IStorage ptr is Released and is
// NULL, its child IStorage/IStream pointers will not be valid,
// for use, but we still need to Release them if they exist.
//
// - If eNodeOp is NODE_INC_TOPSTG, then see if pvcn's _pstg is not
// NULL and call VirtualCtrNode::Close on it to release it. if
// eNodeOp is NODE_EXC_TOPSTG, skip this step
// - Assign pvcn's _pvcnChild to pvcnTrav and pvcn's _pvsnStream
// to pvsnTrav
// - If pvsnTrav is not NULL (i.e pvcn has child VirtualStmNodes),
// in a loop -
// -Check if pvsnTrav's _pstm is not NULL, if not Call
// VirtualStmNode::Close in it to release, else skip it.
// -Advance pvsnTrav to bext VirtualStmNode _pvsnSister &
// go back to top of loop.
// - If pvcnTrav is not NULL (ie pvcn has child VirtualCtrNodes),
// in a loop -
// - Call ParseVirtualDFAndCloseOpenStgsStms recursively
// Pl. note it is called with NODE_INC_TOPSTG always.
// - Advance pvcnTrav to next sister VirtualCtrNode i.e.
// _pvcnSister and go back to top of loop.
//--------------------------------------------------------------------------
HRESULT ParseVirtualDFAndCloseOpenStgsStms(
VirtualCtrNode *pvcn,
NODE_OP eNodeOp)
{
HRESULT hr = S_OK;
VirtualStmNode *pvsnTrav = NULL;
VirtualCtrNode *pvcnTrav = NULL;
DH_FUNCENTRY(
&hr,
DH_LVL_DFLIB,
_TEXT("ParseVirtualDFAndCloseOpenStgsStms"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
DH_ASSERT(NULL != pvcn);
DH_ASSERT((NODE_INC_TOPSTG == eNodeOp) ||
(NODE_EXC_TOPSTG == eNodeOp));
if((S_OK == hr) && (NODE_INC_TOPSTG == eNodeOp))
{
if(NULL != pvcn->GetIStoragePointer())
{
hr = pvcn->Close();
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Close"));
}
}
if(S_OK == hr)
{
pvsnTrav = pvcn->GetFirstChildVirtualStmNode();
pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
// Release IStream pointers if any.
while((NULL != pvsnTrav) && (S_OK == hr))
{
if(NULL != pvsnTrav->GetIStreamPointer())
{
hr = pvsnTrav->Close();
DH_HRCHECK(hr, TEXT("VirtualStmNode::Close"));
}
pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode();
}
// Next recurse into the child VirtualCtrNodes of this VirtualCtrNode
while((NULL != pvcnTrav) && (S_OK == hr))
{
hr = ParseVirtualDFAndCloseOpenStgsStms(
pvcnTrav,
NODE_INC_TOPSTG);
DH_HRCHECK(hr, TEXT("ParseVirtualDFAndCloseOpenStgsStms"));
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
}
}
return hr;
}
//-------------------------------------------------------------------------
// Function: ParseVirtualDFAndCommitAllOpenStgs
//
// Synopsis: This function parses the VirtualDF tree and calls commit
// on all open IStorages pointers under passed in VirtualCtrNode
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode
// [grfCommitFlags] - Commit flags.
// [eNodeOp] - NODE_INC_TOPSTG / NODE_EXC_TOPSTG
//
// Returns: HRESULT
//
// History: 23-July-96 NarindK Created.
//
// Notes: - Assign pvcn's _pvcnChild, if not NULL, to local var pvcnTrav.
// - If pvcnTrav is not NULL (ie pvcn has child VirtualCtrNodes),
// traverse the tree in loop to reach last child.
// - while pvcnTrav is not equal to pvcn and hr is S_OK, loop
// - If pvcnTrav has IStoragePointer, call Commit.
// - If pvcnTrav has sister nodes, call the function
// recursively with NODE_INC_TOPSTG always.
// - Assgin pvcnTrav's parent to pvcnTrav and go back
// to top of loop.
// - if eNodeOp is equal to NODE_INC_TOPSTG and hr is S_OK, then
// commit the top storage pvcn, else skip commiting it.
//--------------------------------------------------------------------------
HRESULT ParseVirtualDFAndCommitAllOpenStgs(
VirtualCtrNode *pvcn,
DWORD grfCommitMode,
NODE_OP eNodeOp)
{
HRESULT hr = S_OK;
VirtualCtrNode *pvcnTrav = NULL;
DH_FUNCENTRY(
&hr,
DH_LVL_DFLIB,
_TEXT("ParseVirtualDFAndCommitAllOpenStgs"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
DH_ASSERT(NULL != pvcn);
DH_ASSERT((NODE_INC_TOPSTG == eNodeOp) ||
(NODE_EXC_TOPSTG == eNodeOp));
if(S_OK == hr)
{
pvcnTrav = pvcn;
while(NULL != pvcnTrav->GetFirstChildVirtualCtrNode())
{
pvcnTrav = pvcnTrav->GetFirstChildVirtualCtrNode();
}
DH_ASSERT(NULL != pvcnTrav);
}
// Commit this storage, next commit any sister VirtualCtrNodes it might
// have and commit those by recursing into them, then go to parent and
// repeat. if parent is equal to pvcnParent, quit the loop
while((pvcn != pvcnTrav) && (S_OK == hr))
{
if(NULL != pvcnTrav->GetIStoragePointer())
{
hr = pvcnTrav->Commit(grfCommitMode);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Commit"));
}
while((NULL != pvcnTrav->GetFirstSisterVirtualCtrNode()) &&
(S_OK == hr))
{
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
hr = ParseVirtualDFAndCommitAllOpenStgs(
pvcnTrav,
grfCommitMode,
NODE_INC_TOPSTG);
DH_HRCHECK(hr, TEXT("ParseVirtualDFAndCommitAllOpenStgs"));
}
// Go to Parent VirtualCtrNode and commit them
pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
}
if((S_OK == hr) &&
(NODE_INC_TOPSTG == eNodeOp) &&
(NULL != pvcn->GetIStoragePointer()))
{
hr = pvcn->Commit(grfCommitMode);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Commit"));
}
return hr;
}
//-------------------------------------------------------------------------
//
// The following utilitiy functions are to calculate the CRC for a docfile
// These are independent of VirtualDF tree or any other base code implement-
// ation.
//
//-------------------------------------------------------------------------
//+-------------------------------------------------------------------------
// Function: CalculateCRCForDocFile
//
// Synopsis: Calulates CRC for the disk docfile.
//
// Arguments: [pIStorage] - pointer to IStorage
// [crcflags] - what stuff to include in the crc
// [pdwCRC] - pointer to CRC
//
// Returns: HRESULT
//
// History: 30-May-96 NarindK Created.
// 24-Jul-97 MikeW Include state bits
// 02-Apr-98 georgis read in chunks
//
// Notes: For IStorages, only name is CRC'd. For IStorages/IStreams,
// both name and data are CRC'd.
//
// Please not that this function will not indicate a failure if
// and whenver the IEnumSTATSTG->Next returns fail, that just
// indicates the completion of enumeration sequence.
//
// If VERIFY_OP is equal to VERIFY_INC_TOPSTG_NAME, then the func
// goes ahead and calculates CRC for toplevel storage name also
// else if it is equal to VERIFY_EXC_TOPSTG_NAME, it doesn't
// include the CRC for top level storage name. Pl. note that
// the recursive call to itself in function includes VERIFY_INC_
// TOPSTG_NAME, so this parameter is used only for TOP level
// storage that is passed in (pointed by pIStorage).
//
// - if VERIFY_OP is VERIFY_INC_TOPSTG_NAME then,
// -Call pIStorage->Stat to get STATSTG structure for passed
// IStorage.
// -Call CalculateCRCForName to get the CRC for name of this
// storage obtained from STATSTG structure.
// -Fold the CRC into grand CRC pdwCRC.
// -Call pIStorage->Enumerate to get LPENUMSTATSTG for storage.
// -Call lpEnumStatStg->Next to get next element in enumeration
// sequence. If it returns S_FALSE, means no elements to enum
// earte, so just return w/o any error.
// -Else loop till hr is S_OK.
// -If node is of type STGSTY_STORAGE, then
// -Open the child IStorage.
// -Make a recursive call to calculate CRC for this
// child Istorage to self CalculateCRCForDocFile.
// -Fold the CRC from above call into grand CRC pdwCRC.
// -Release the child IStorage
// -If node is of type STGSTY_STREAM, then
// -Call CalculateCRCForDocFileStmData to calculate CRC
// for stream data.
// -Call CalculateCRCForName to calculate CRC for its
// name.
// -Fold the above two into grand CRC pdwCRC.
// -Get the next element in enumeration sequence. If it returns
// S_FALSE, then simply return w/o any error.
// -Else go back to top of loop and repeat.
//--------------------------------------------------------------------------
HRESULT CalculateCRCForDocFile(
IStorage *pIStorage,
DWORD crcflags,
DWORD *pdwCRC,
DWORD dwChunkSize)
{
HRESULT hr = S_OK;
LPENUMSTATSTG lpEnumStatStg = NULL;
ULONG *pceltFetched = NULL;
LPSTORAGE pIStorageChild = NULL;
DWORD dwCurrStgCRC = 0;
DWORD dwCurrStgNameCRC= 0;
DWORD dwCurrStmNameCRC= 0;
DWORD dwCurrStmDataCRC= 0;
BOOL fIEnumNextFail = FALSE;
ULONG i = 0;
LPTSTR ptszName = NULL;
LPTSTR ptszNameStm = NULL;
LPTSTR ptszNameStg = NULL;
LPOLESTR poszNameStg = NULL;
STATSTG statStg;
STATSTG statStgEnum;
DWORD statflag = STATFLAG_DEFAULT;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CalculateCRCForDocFile"));
DH_VDATEPTRIN(pIStorage, IStorage) ;
DH_VDATEPTROUT(pdwCRC, DWORD) ;
DH_ASSERT(NULL != pIStorage);
DH_ASSERT(NULL != pdwCRC);
// Initialization
statStg.pwcsName = NULL;
statStgEnum.pwcsName = NULL;
// Initialize out parameter
*pdwCRC = CRC_PRECONDITION;
// Call Stat on the passed IStorage to get its name and state bits
if (! (CRC_INC_TOPSTG_NAME & crcflags))
{
statflag = STATFLAG_NONAME;
}
if(S_OK == hr)
{
hr = pIStorage->Stat(&statStg, statflag);
DH_HRCHECK(hr, TEXT("IStorage::Stat")) ;
}
if (CRC_INC_STATEBITS & crcflags)
{
// Fold the CRC into grand CRC
MUNGECRC(*pdwCRC, statStg.grfStateBits);
DH_TRACE((
DH_LVL_CRCDUMP,
TEXT("statebits=0x%08x, crc=0x%08x"),
statStg.grfStateBits,
*pdwCRC));
}
// If crcflags includes CRC_INC_TOPSTG_NAME, then calculate and
// include the top level storage name in calculating grand CRC.
if(CRC_INC_TOPSTG_NAME & crcflags)
{
DH_ASSERT(NULL != statStg.pwcsName);
// Find the CRC for the storage name
if(S_OK == hr)
{
//Convert WCHAR to TCHAR
hr = OleStringToTString(statStg.pwcsName, &ptszName);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
}
if(S_OK == hr)
{
hr = CalculateCRCForName(ptszName, &dwCurrStgNameCRC);
DH_HRCHECK(hr, TEXT("CalculateCRCForDocFileNames")) ;
}
// Fold the CRC into grand CRC
MUNGECRC(*pdwCRC, dwCurrStgNameCRC);
DH_TRACE((
DH_LVL_CRCDUMP,
TEXT("storage=%s, crc=0x%08x"),
ptszName,
*pdwCRC));
// Clean up
if(NULL != statStg.pwcsName)
{
CoTaskMemFree(statStg.pwcsName);
statStg.pwcsName = NULL;
}
if(NULL != ptszName)
{
delete ptszName;
ptszName = NULL;
}
}
// Get the enumerator so that we could enumerate this storage
if(S_OK == hr)
{
hr = pIStorage->EnumElements(0, NULL, 0, &lpEnumStatStg);
DH_HRCHECK(hr, TEXT("IStorage::EnumElements")) ;
}
// if successful to get enumerator, get the first element of the enumeration
// sequence.
if ( S_OK == hr )
{
hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
if(S_FALSE == hr)
{
fIEnumNextFail = TRUE;
}
}
// Loop through till lpEnumStatStg->Next returns FALSE which is desired
// sequene or some other error happens
while(S_OK == hr)
{
// If the element is an IStorage, open this and make a recursive call
// to CalculateCRCForDocFile function.
if (STGTY_STORAGE == statStgEnum.type)
{
//Convert WCHAR to TCHAR
hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStg);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
if(S_OK == hr)
{
// Convert TCHAR to OLECHAR
hr = TStringToOleString(ptszNameStg, &poszNameStg);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = pIStorage->OpenStorage(
poszNameStg,
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
NULL,
0,
&pIStorageChild);
DH_HRCHECK(hr, TEXT("IStorage::OpenStorage")) ;
}
if (S_OK == hr)
{
// Make recursive call including CRC_INC_TOPSTG_NAME
hr = CalculateCRCForDocFile(
pIStorageChild,
crcflags | CRC_INC_TOPSTG_NAME,
&dwCurrStgCRC);
DH_HRCHECK(hr, TEXT("CalculateCRCForDocFile")) ;
}
// Fold the CRC for contained IStorage into grand CRC
MUNGECRC(*pdwCRC, dwCurrStgCRC);
// Release the storage pointer
if(NULL != pIStorageChild)
{
pIStorageChild->Release();
pIStorageChild = NULL;
}
}
else
// If the element is an IStream, calculate CRC for its name and Data.
if (STGTY_STREAM == statStgEnum.type)
{
// Calulate CRC for IStream Data.
if(S_OK == hr)
{
//Convert WCHAR to TCHAR
hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStm);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
}
if(S_OK == hr)
{
hr = CalculateCRCForDocFileStmData(
pIStorage,
ptszNameStm,
statStgEnum.cbSize.LowPart,
&dwCurrStmDataCRC,
dwChunkSize);
DH_HRCHECK(hr, TEXT("CalculateCRCForDocFileStmData"));
}
// Calulate CRC for IStream Name.
if(S_OK == hr)
{
hr = CalculateCRCForName(
ptszNameStm,
&dwCurrStmNameCRC);
DH_HRCHECK(hr, TEXT("CalculateCRCForName"));
DH_TRACE((
DH_LVL_CRCDUMP,
TEXT("stream %s, name crc=0x%08x, data crc=0x%08x"),
ptszNameStm,
dwCurrStmNameCRC,
dwCurrStmDataCRC));
}
// Fold the CRC's for contained IStream into grand CRC
MUNGECRC(*pdwCRC, dwCurrStmDataCRC);
MUNGECRC(*pdwCRC, dwCurrStmNameCRC);
}
else
// The element is neither IStorage nor IStream, report error.
{
hr = E_UNEXPECTED;
}
// Clean up
if(NULL != statStgEnum.pwcsName)
{
CoTaskMemFree(statStgEnum.pwcsName);
statStgEnum.pwcsName = NULL;
}
if(NULL != ptszNameStm)
{
delete ptszNameStm;
ptszNameStm = NULL;
}
if(NULL != ptszNameStg)
{
delete ptszNameStg;
ptszNameStg = NULL;
}
if(NULL != poszNameStg)
{
delete poszNameStg;
poszNameStg = NULL;
}
// Get the next element in the enumeration sequence
if(S_OK == hr)
{
hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
if(S_FALSE == hr)
{
fIEnumNextFail = TRUE;
}
}
}
// IEnumSTATSTG->Next would return S_FALSE if it can't enumerate the
// next element because there might not be any elements to enumerate
// hence it doesn't indicate an error for this function, but is just
// a condition for looping through the total docfile structure, hence
// don't reprot failure because of it.
if(TRUE == fIEnumNextFail)
{
hr = S_OK;
}
// Clean up
if (NULL != lpEnumStatStg)
{
lpEnumStatStg->Release();
lpEnumStatStg = NULL;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: CalculateCRCForDocFileStmData
//
// Synopsis: Calulates CRC for the disk docfile's stream data.
//
// Arguments: [pIStorage] - pointer to parent storage
// [ptcsName] - pointer to name string
// [cbSize] - size of the data to be read.
// [pdwCurrStmDataCRC]- pointer to returned CRC
//
// Returns: HRESULT
//
// History: 30-May-96 NarindK Created.
// 02-Apr-98 georgis Use CalculateStreamDataCRC
//
//--------------------------------------------------------------------------
HRESULT CalculateCRCForDocFileStmData(
LPSTORAGE pIStorage,
LPTSTR ptcsName,
DWORD cbSize,
DWORD *pdwCurrStmDataCRC,
DWORD dwChunkSize)
{
HRESULT hr = S_OK;
LPSTREAM pIStreamChild = NULL;
LPOLESTR pOleStrTemp = NULL;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, TEXT("CalculateCRCForDocFileStmData"));
DH_VDATEPTRIN(pIStorage, IStorage) ;
DH_VDATESTRINGPTR(ptcsName) ;
DH_VDATEPTROUT(pdwCurrStmDataCRC, DWORD) ;
DH_ASSERT(NULL != pIStorage);
DH_ASSERT(NULL != ptcsName);
DH_ASSERT(NULL != pdwCurrStmDataCRC);
// Open the stream
hr = TStringToOleString(ptcsName, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
if ( S_OK == hr )
{
hr = pIStorage->OpenStream(
pOleStrTemp,
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&pIStreamChild);
DH_HRCHECK(hr, TEXT("IStorage::OpenStream")) ;
}
if ( S_OK == hr )
{
// Calculate the CRC for the stream data
hr=CalculateStreamDataCRC(
pIStreamChild,
cbSize,
pdwCurrStmDataCRC,
dwChunkSize);
DH_HRCHECK(hr, TEXT("CalculateStreamDataCRC"));
}
if (NULL!= pIStreamChild)
{
pIStreamChild->Release();
}
if (NULL != pOleStrTemp)
{
delete pOleStrTemp;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: CalculateCRCForDocFileStmData
//
// Synopsis: Calulates CRC for the disk docfile's stream data.
//
// Arguments: [ptcsName] - ? not used
// [pIChildStream] - pointer to the opened stream
// [cbSize] - size of the data to be read.
// [pdwCurrStmDataCRC]- pointer to returned CRC
//
// Returns: HRESULT
//
// History: 15-Nov-96 JiminLi Created.
// 02-Apr-98 georgis Use CalculateStreamDataCRC
//
// Notes: CalculateStreamDataCRC actually obsoletes this function
// It remains for compatibility with the old tests
//
//--------------------------------------------------------------------------
HRESULT CalculateCRCForDocFileStmData(
LPTSTR ptcsName,
LPSTREAM pIChildStream,
DWORD cbSize,
DWORD *pdwCurrStmDataCRC,
DWORD dwChunkSize)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, TEXT("CalculateCRCForDocFileStmData"));
DH_VDATEPTRIN(pIChildStream, IStream) ;
DH_VDATEPTROUT(pdwCurrStmDataCRC, DWORD) ;
DH_ASSERT(NULL != pdwCurrStmDataCRC);
DH_ASSERT(0 != cbSize);
// The stream is kept open before calling this function
DH_ASSERT(NULL != pIChildStream);
// Calculate the CRC for the stream data
hr=CalculateStreamDataCRC(
pIChildStream,
cbSize,
pdwCurrStmDataCRC,
dwChunkSize);
DH_HRCHECK(hr, TEXT("CalculateStreamDataCRC"));
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: EnumerateDiskDocFile
//
// Synopsis: Enumerates a disk docfile.
//
// Arguments: [pIStorage] - pointer to IStorage
// [eVerifyOp] - VERIFY_SHORT or VERIFY_DETAIL
// [pdwNumStg] - pointer to number of Storages in doc hierarchy.
// [pdwNumStm] - pointer to number of streams in doc hierarchy
//
// Returns: HRESULT
//
// History: 3-June-96 NarindK Created.
//
// Notes: pdwNumStg, pdwNumStm may be NULL if user is not interested in
// these values to be returned back. eVerifyOp should normally
// be specified as VERIFY_SHORT unless test requires it otherwise
//
// -Count the passed in pIStorage as 1 in pNumStg count.
// -Call pIStorage->EnumElements to get LPENUMSTATSTG lpEnumStatStg
// -Call lpEnumStatStg->Next to get next node. If it returns
// S_FALSE, that indicates no elements to enumerate, so return
// without any error.
// -Else loop till hr is S_OK
// -if node is of type STGTY_STORAGE, then
// -open that child storage and make a recursive call to
// EnumerateDiskDocFile passing it pointer to opened
// child storage, and cChildStg and cChildStm local
// variables for count.
// -close the child storage opened.
// -Update the pNumStg, pNumStm based on above recursive
// call's out parameters cChildStg and CChildStm.
// -if node is of type STGTY_STREAM, then update pNumStm count
// - if flag VERIFY_DETAIL is passed in, then open that
// stream and read its contents. This verification
// is useful in cases like corruption tests where this
// verification ensures proper stability of OLE under
// such situations.
// -Get the next element in enumeration sequence.
// -Reinitilize the local variables cChildStg, cChildStm.
// -Go back to top of loop and repeat.
//--------------------------------------------------------------------------
HRESULT EnumerateDiskDocFile(
LPSTORAGE pIStorage,
VERIFY_OP eVerifyOp,
ULONG *pNumStg,
ULONG *pNumStm )
{
HRESULT hr = S_OK;
LPMALLOC pMalloc = NULL;
LPENUMSTATSTG lpEnumStatStg = NULL;
ULONG *pceltFetched = NULL;
LPSTORAGE pIStorageChild = NULL;
BOOL fIEnumNextFail = FALSE;
ULONG cChildStg = 0;
ULONG cChildStm = 0;
LPSTREAM pIStreamChild = NULL;
LPOLESTR pocsBuffer = NULL;
LPTSTR ptszNameStg = NULL;
LPOLESTR poszNameStg = NULL;
LPTSTR ptszNameStm = NULL;
LPOLESTR poszNameStm = NULL;
ULONG culRead = 0;
ULONG culCurBufferLen = 0;
STATSTG statStgEnum;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("EnumerateDiskDocFile"));
DH_VDATEPTRIN(pIStorage, IStorage) ;
if(NULL != pNumStg)
{
DH_VDATEPTROUT(pNumStg, ULONG) ;
}
if(NULL != pNumStm)
{
DH_VDATEPTROUT(pNumStm, ULONG) ;
}
DH_ASSERT(NULL != pIStorage);
// Initialization
statStgEnum.pwcsName = NULL;
// 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")) ;
}
// Call EnumElements on passed IStorage to enumerate it.
if(S_OK == hr)
{
// Initialize out parameter
if(NULL != pNumStg)
{
// Count the storage passed in.
*pNumStg = 1;
}
if(NULL != pNumStm)
{
*pNumStm = 0;
}
hr = pIStorage->EnumElements(0, NULL, 0, &lpEnumStatStg);
DH_HRCHECK(hr, TEXT("IStorage::EnumElements")) ;
}
// if successful to get enumerator, get the first element of the enumeration
// sequence.
if ( S_OK == hr )
{
hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
if(S_FALSE == hr)
{
fIEnumNextFail = TRUE;
}
}
// Loop through till lpEnumStatStg->Next returns FALSE which is desired
// sequence or some other error happens
while(S_OK == hr)
{
// If the element is an IStorage, open this and make a recursive call
// to EnumerateDocFile function.
if (STGTY_STORAGE == statStgEnum.type)
{
//Convert WCHAR to TCHAR
hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStg);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
if(S_OK == hr)
{
// Convert TCHAR to OLECHAR
hr = TStringToOleString(ptszNameStg, &poszNameStg);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = pIStorage->OpenStorage(
poszNameStg,
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
NULL,
0,
&pIStorageChild);
DH_HRCHECK(hr, TEXT("IStorage::OpenStorage")) ;
}
if (S_OK == hr)
{
// Recursive call to EnumerateDiskDocFile
hr = EnumerateDiskDocFile(
pIStorageChild,
eVerifyOp,
&cChildStg,
&cChildStm);
DH_HRCHECK(hr, TEXT("EnumerateDiskDocFile")) ;
}
// Release the storage pointer
if(NULL != pIStorageChild)
{
pIStorageChild->Release();
pIStorageChild = NULL;
}
// Release string pointers.
if(NULL != ptszNameStg)
{
delete ptszNameStg;
ptszNameStg = NULL;
}
if(NULL != poszNameStg)
{
delete poszNameStg;
poszNameStg = NULL;
}
// Update number of storage and stream objects, if required.
if((NULL != pNumStg) && (0 != cChildStg))
{
*pNumStg = cChildStg + *pNumStg;
}
if((NULL != pNumStm) && (0 != cChildStm))
{
*pNumStm = cChildStm + *pNumStm;
}
}
else
if (STGTY_STREAM == statStgEnum.type)
{
if(NULL != pNumStm)
{
(*pNumStm)++;
}
if(VERIFY_DETAIL == eVerifyOp)
{
//Attempt to open and read the stream. Useful for corruption
// tests to see that OLE doesn't GPF under those conditions.
//Convert WCHAR to TCHAR
hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStm);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
if(S_OK == hr)
{
// Convert TCHAR to OLECHAR
hr = TStringToOleString(ptszNameStm, &poszNameStm);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
// Open the stream.
if(S_OK == hr)
{
hr = pIStorage->OpenStream(
poszNameStm,
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&pIStreamChild);
DH_HRCHECK(hr, TEXT("IStorage::OpenStream")) ;
}
// Read the stream in loop
while(( culCurBufferLen < statStgEnum.cbSize.LowPart) &&
(S_OK == hr))
{
if ( S_OK == hr )
{
pocsBuffer = new OLECHAR [STM_BUFLEN];
if (pocsBuffer == NULL)
{
hr = E_OUTOFMEMORY;
}
}
if ( S_OK == hr )
{
// Initialize the buffer
memset(pocsBuffer, '\0', STM_BUFLEN);
// Read the stream.
hr = pIStreamChild->Read(
pocsBuffer,
STM_BUFLEN,
&culRead);
DH_HRCHECK(hr, TEXT("IStream::Read")) ;
}
// Release the buffer
if(NULL != pocsBuffer)
{
delete [] pocsBuffer;
pocsBuffer = NULL;
}
// Increment culCurBufferLen
culCurBufferLen = culCurBufferLen + culRead;
}
// Release the stream
if(NULL != pIStreamChild)
{
pIStreamChild->Release();
pIStreamChild = NULL;
}
// Release string pointers.
if(NULL != ptszNameStm)
{
delete ptszNameStm;
ptszNameStm = NULL;
}
if(NULL != poszNameStm)
{
delete poszNameStm;
poszNameStm = NULL;
}
}
}
else
// The element is neither IStorage nor IStream, report error.
{
hr = E_UNEXPECTED;
}
// Clean up
if(NULL != statStgEnum.pwcsName)
{
pMalloc->Free(statStgEnum.pwcsName);
statStgEnum.pwcsName = NULL;
}
// Get the next element in the enumeration sequence
if(S_OK == hr)
{
hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
if(S_FALSE == hr)
{
fIEnumNextFail = TRUE;
}
}
// Reinitialize the variables
cChildStg = 0;
cChildStm = 0;
}
// IEnumSTATSTG->Next returning S_FALSE indicates end of traversal in
// docfile hierarchy, not an error.
if(TRUE == fIEnumNextFail)
{
hr = S_OK;
}
// Clean up
if (NULL != lpEnumStatStg)
{
lpEnumStatStg->Release();
lpEnumStatStg = NULL;
}
if(NULL != pMalloc)
{
pMalloc->Release();
pMalloc = NULL;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: GenerateVirtualDFFromDiskDF
//
// Synopsis: Enumerates a disk docfile and creates an in memory virtual
// DocFile tree for the docfile.
//
// Arguments: [pNewVirtualDF] - Pointer to new VirtualDF tree being made.
// [ptszRootDFName] - Pointer to name of root Disk file.
// [grfMode] - Mode to open the root storage
// [ppvcnRoot] - pointer to pointer to root of VirtualDF.
// [pIRootStg] - Default value is NULL, when fDFOpened is TRUE,
// then pIRootStg must not be NULL, it is RootStg
// pointer
// [fDFOpened] - Default value is FALSE, i.e. the docfile is not
// opened, StgOpenStorage is called to open it.
// When it's TRUE, the pIRootStg is the stg pointer.
//
// Returns: HRESULT
//
// History: 5-June-96 NarindK Created.
// 3-Feb-97 JiminLi Adapted
//
// Notes: -Call TStringToOleString to convert given DocFile name to
// OLECHAR.
// - Call StgOpenStorage to open Root storage.
// -Call GenVirtualCtrNode to generate the root *ppvcnRoot of new
// VirtualDocFile tree being made passing it name from above Stat
// call. If successful, assocaite disk root IStorage with the
// root VirtualCtrNode's _pstg parameter.
// -Call GenerateRemVirtualDFTree to generate rest of tree, passing// it the new rootgenerated above and pIStorage.
// -If successful, call VirtualDF::Associate to associate this
// new root with the VirtualDF tree, else reassign *ppvcnRoot
// to NULL in case of failure.
//
// Please note that the Root storage opened during this call will
// be released during VirtualDF tree deletion that deletes all
// the VirtualCtrNodes in the tree & Destructor of VirtualCtrNodes
// does a final release on the storage pointers, if they are valid
// Also note that as result of this function, all other storage/
// streams are closed, except the Root storage.
//--------------------------------------------------------------------------
HRESULT GenerateVirtualDFFromDiskDF(
VirtualDF *pNewVirtualDF,
LPTSTR ptszRootDFName,
DWORD grfMode,
VirtualCtrNode **ppvcnRoot,
LPSTORAGE pIRootStg,
BOOL fDFOpened,
ULONG ulSeed)
{
HRESULT hr = S_OK;
LPSTORAGE pIStorage = NULL;
LPOLESTR pOleStrTemp = NULL;
ULONG i = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GenerateVirtualDFFromDiskDF"));
DH_VDATESTRINGPTR(ptszRootDFName) ;
DH_VDATEPTROUT(ppvcnRoot, PVCTRNODE) ;
DH_VDATEPTROUT(pNewVirtualDF, VirtualDF) ;
DH_ASSERT(NULL != ptszRootDFName);
DH_ASSERT(NULL != ppvcnRoot);
DH_ASSERT(NULL != pNewVirtualDF);
if (fDFOpened)
{
DH_ASSERT(NULL != pIRootStg);
pIStorage = pIRootStg;
}
else
{
DH_ASSERT(0 != grfMode);
}
if ( S_OK == hr )
{
// Initialize out parameter
*ppvcnRoot = NULL;
}
if (!fDFOpened && (S_OK == hr))
{
// Convert TCHAR to OLECHAR
hr = TStringToOleString(ptszRootDFName, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if (!fDFOpened && (S_OK == hr))
{
// Try opening the docfile
// StgOpenStorage returns STG_E_LOCKVIOLATION is concurrent API calls
// are made, so this is the hack for workaround the problem.
// BUGBUG : Remove this loop once the feature is implemented in OLE.
// BUGBUG : ntbug#114779 Affects DCOM95 only. ntbug#41249 fixed
#if (WINVER<0x500) //NT5 is lockviolation fixed
for(i=0; i<NRETRIES; i++) // NRETRIES has been defined as 5
{
#endif
hr = StgOpenStorage(
pOleStrTemp,
NULL,
grfMode,
NULL,
0,
&pIStorage);
#if (WINVER<0x500) //NT5 is lockviolation fixed
if ( (S_OK == hr) || (STG_E_LOCKVIOLATION != hr) )
{
break;
}
Sleep(NWAIT_TIME);
}
#endif
}
if ( S_OK == hr )
{
// Call to create the VirtualDF tree root.
hr = GenVirtualCtrNode(ptszRootDFName, ppvcnRoot);
DH_HRCHECK(hr, TEXT("GenerateVirtualDFRootFromDiskStg")) ;
}
if ( S_OK == hr )
{
// Create the remaining VirtualDF tree.
hr = GenerateRemVirtualDFTree(*ppvcnRoot, pIStorage);
DH_HRCHECK(hr, TEXT("CreateRemVirtualDFTree")) ;
}
if (S_OK != hr)
{
// The tree couldn't be successfully created, return NULL in out
// parameter.
*ppvcnRoot = NULL;
}
else
{
// Associate the root VirtualCtrNode with the VirtualDF tree.
hr = pNewVirtualDF->Associate(*ppvcnRoot, pIStorage, ulSeed);
DH_HRCHECK(hr, TEXT("VirtualDF::Associate")) ;
}
// Clean up
if(NULL != pOleStrTemp)
{
delete pOleStrTemp;
pOleStrTemp = NULL;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: GenerateVirtualDFFromDiskDF
//
// Synopsis: Enumerates a disk docfile and creates an in memory virtual
// DocFile tree for the docfile.
//
// Arguments: [pNewVirtualDF] - Pointer to new VirtualDF tree being made.
// [ptszRootDFName] - Pointer to name of root Disk file.
// [grfMode] - Mode to open the root storage
// [ppvcnRoot] - pointer to pointer to root of VirtualDF.
// [ulSeed] - pointer to pointer to root of VirtualDF.
//
// Notes: Call the above function with filled in params that are
// normally defaulted with the defaults. Seed is at the
// end, so we need them.
// This is a convenience function.
//
//--------------------------------------------------------------------------
HRESULT GenerateVirtualDFFromDiskDF(
VirtualDF *pNewVirtualDF,
LPTSTR ptszRootDFName,
DWORD grfMode,
VirtualCtrNode **ppvcnRoot,
ULONG ulSeed)
{
return GenerateVirtualDFFromDiskDF(
pNewVirtualDF,
ptszRootDFName,
grfMode,
ppvcnRoot,
NULL,
FALSE,
ulSeed);
}
//+-------------------------------------------------------------------------
// Function: GenerateRemVirtualDFTree
//
// Synopsis: Creates rest of in memory virtual DocFile tree for a given
// Disk Docfile. Internal function local to this file.
//
// Arguments: [pvcnParent] - pointer to root VirtualCtrNode
// [pIStgParent] - pointer to Disk IStorage assoc. with above.
//
// Returns: HRESULT
//
// History: 5-June-96 NarindK Created.
//
// Notes: -Call pIStgParent->Enumerate to get LPENUMSTATSTG for storage.
// -Call lpEnumStatStg->Next to get next element of enumeration.
// if it returns S_FALSE, that means there is nothing to enum-
// erate, so just return without nay error.
// -Else loop till hr is S_OK
// -If node is of type STGTY_STORAGE then
// -open this child storage.
// -Call GenVirtualCtrNode to create a corresponding
// VirtualCtrNode for this storage.
// -Call AppendChildCtr or AppendSisterCtr as case is.
// -Call parent's IncreaseChildrenStgCount to indicate
// a new VirtualCtrNode is added.
// -Make a recursive call to GenVirtualCtrNode.
// -Release the child storage pointer and remember the old
// sibling.
// -If node is of type STGSTY_STREAM then
// -Call GenVirtualStmNode to create a corresponding
// VirtualStmNode for this stream.
// -Call AppendChildStm or AppendSisterStm as case is.
// -Call parent's IncreaseChildrenStmCount to indicate
// a new VirtualStmNode is added.
// -Remember the old sibling.
// -Reinitialize local variables and call Next on the enumera-
// or. If it returns S_FALSE, then exist out of loop w/o
// any error.
// -Else go back to top of loop and repeat.
//--------------------------------------------------------------------------
HRESULT GenerateRemVirtualDFTree(
VirtualCtrNode *pvcnParent,
LPSTORAGE pIStgParent)
{
HRESULT hr = S_OK;
LPMALLOC pMalloc = NULL;
ULONG *pceltFetched = NULL;
LPSTORAGE pIStorageChild = NULL;
VirtualCtrNode *pvcnChild = NULL;
VirtualStmNode *pvsnChild = NULL;
VirtualCtrNode *pvcnOldSister = NULL;
VirtualStmNode *pvsnOldSister = NULL;
LPENUMSTATSTG lpEnumStatStg = NULL;
BOOL fFirstChild = TRUE;
BOOL fFirstStream = TRUE;
BOOL fIEnumNextFail = FALSE;
LPTSTR ptszNameStg = NULL;
LPTSTR ptszNameStm = NULL;
LPOLESTR pOleStrTemp = NULL;
STATSTG statStgEnum;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GenerateRemVirtualDFTree"));
// Initialization
statStgEnum.pwcsName = NULL;
// 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")) ;
}
if ( S_OK == hr )
{
// Get an Enumerator for given IStorage
hr = pIStgParent->EnumElements(0, NULL, 0, &lpEnumStatStg);
DH_HRCHECK(hr, TEXT("IStorage::EnumElements")) ;
}
// if successful to get enumerator, get the first element of the enumeration
// sequence.
if ( S_OK == hr )
{
hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
if(S_FALSE == hr)
{
fIEnumNextFail = TRUE;
}
}
while(S_OK == hr)
{
// If the element is an IStorage, open this and make a recursive call
// to self.
if (STGTY_STORAGE == statStgEnum.type)
{
if(S_OK == hr)
{
//Convert WCHAR to TCHAR
hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStg);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
}
if(S_OK == hr)
{
// Convert TCHAR to OLECHAR
hr = TStringToOleString(ptszNameStg, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
hr = pIStgParent->OpenStorage(
pOleStrTemp,
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
NULL,
0,
&pIStorageChild);
DH_HRCHECK(hr, TEXT("IStorage::OpenStorage")) ;
// Add to tree
if (S_OK == hr)
{
hr = GenVirtualCtrNode(
ptszNameStg,
&pvcnChild);
}
if (S_OK == hr)
{
if(fFirstChild == TRUE)
{
hr = pvcnParent->AppendChildCtr(pvcnChild);
pvcnParent->IncreaseChildrenStgCount();
fFirstChild = FALSE;
}
else
{
hr = pvcnOldSister->AppendSisterCtr(pvcnChild);
pvcnParent->IncreaseChildrenStgCount();
}
}
if (S_OK == hr)
{
// Recursive call to self
hr = GenerateRemVirtualDFTree(pvcnChild, pIStorageChild);
DH_HRCHECK(hr, TEXT("EnumerateDiskDocFile")) ;
}
// Release the storage pointer
if(NULL != pIStorageChild)
{
pIStorageChild->Release();
pIStorageChild = NULL;
}
// Remember the old sibling
pvcnOldSister = pvcnChild;
}
else
// The element is an IStream.
if (STGTY_STREAM == statStgEnum.type)
{
// Add to tree
if (S_OK == hr)
{
if(S_OK == hr)
{
// Convert WCHAR to TCHAR
hr = OleStringToTString(statStgEnum.pwcsName, &ptszNameStm);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
}
// BUGBUG:The cbSize used during creation is a DWORD. Assumption
// cbSize.LowPart contains the size information hence.
hr = GenVirtualStmNode(
ptszNameStm,
statStgEnum.cbSize.LowPart,
&pvsnChild);
}
if (S_OK == hr)
{
if(fFirstStream == TRUE)
{
hr = pvcnParent->AppendFirstChildStm(pvsnChild);
pvcnParent->IncreaseChildrenStmCount();
fFirstStream = FALSE;
}
else
{
hr = pvsnOldSister->AppendSisterStm(pvsnChild);
pvcnParent->IncreaseChildrenStmCount();
}
}
// Remember the old sibling
pvsnOldSister = pvsnChild;
}
else
// The element is neither IStorage nor IStream, report error.
{
hr = E_UNEXPECTED;
}
// Cleanup
if(NULL != statStgEnum.pwcsName)
{
pMalloc->Free(statStgEnum.pwcsName);
statStgEnum.pwcsName = NULL;
}
if(NULL != pOleStrTemp)
{
delete pOleStrTemp;
pOleStrTemp = NULL;
}
if(NULL != ptszNameStg)
{
delete ptszNameStg;
ptszNameStg = NULL;
}
if(NULL != ptszNameStm)
{
delete ptszNameStm;
ptszNameStm = NULL;
}
// Reinitialize the variables
pIStorageChild = NULL;
pvcnChild = NULL;
pvsnChild = NULL;
// Get the next element in the enumeration sequence
if(S_OK == hr)
{
hr = lpEnumStatStg->Next(1, &statStgEnum, pceltFetched);
if(S_FALSE == hr)
{
fIEnumNextFail = TRUE;
}
}
}
// IEnumSTATSTG->Next returning S_FALSE indicates end of traversal in
// docfile hierarchy, not an error.
if(TRUE == fIEnumNextFail)
{
hr = S_OK;
}
// Clean up
if (NULL != lpEnumStatStg)
{
lpEnumStatStg->Release();
lpEnumStatStg = NULL;
}
if(NULL != pMalloc)
{
pMalloc->Release();
pMalloc = NULL;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: GenVirtualCtrNode
//
// Synopsis: Creates a VirtualCtrNode and initializes it
//
// Arguments: [ptcsName] - pointer to name for VirtualCtrNode
// [*ppvcnNew] - Returned VirtualCtrNode.
//
// Returns: HRESULT
//
// History: 5-June-96 NarindK Created.
//
// Notes: Creates a VirtualCtrNode and initializes it will pName that
// is passed in. _cChildren and _cStreams are initialized to
// zero.
//--------------------------------------------------------------------------
HRESULT GenVirtualCtrNode(
LPTSTR ptcsName,
VirtualCtrNode **ppvcnNew)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GenVirtualCtrNodeFromDiskStg"));
DH_VDATEPTRIN(ptcsName, TCHAR) ;
DH_VDATEPTROUT(ppvcnNew, PVCTRNODE) ;
DH_ASSERT(NULL != ptcsName);
DH_ASSERT(NULL != ppvcnNew);
// Generate VirtualCtrNode for the stg.
if(S_OK == hr)
{
// Initialize out parameter
*ppvcnNew = NULL;
// Create new VirtualCtrNode
*ppvcnNew = new VirtualCtrNode();
if (NULL == *ppvcnNew)
{
hr = E_OUTOFMEMORY;
}
}
if(S_OK == hr)
{
// Initialize VirtualCtrNode
hr = (*ppvcnNew)->Init(ptcsName, 0, 0);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: GenVirtualStmNode
//
// Synopsis: Creates a VirtualStmNode and initializes it
//
// Arguments: [ptcsName] - pointer to name for VirtualStmNode
// [*ppvcnNew] - Returned VirtualStmNode.
//
// Returns: HRESULT
//
// History: 5-June-96 NarindK Created.
//
// Notes: -Creates a new VirtualStmNode and initializes it with name
// and size passed in.
//--------------------------------------------------------------------------
HRESULT GenVirtualStmNode(
LPTSTR ptcsName,
DWORD cbSize,
VirtualStmNode **ppvsnNew)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GenVirtualStmNode"));
DH_VDATEPTRIN(ptcsName, TCHAR) ;
DH_VDATEPTROUT(ppvsnNew, PVSTMNODE) ;
DH_ASSERT(NULL != ptcsName);
DH_ASSERT(NULL != ppvsnNew);
// Generate VirtualStmNode for the stream.
if(S_OK == hr)
{
*ppvsnNew = new VirtualStmNode();
if (NULL == *ppvsnNew)
{
hr = E_OUTOFMEMORY;
}
}
if(S_OK == hr)
{
hr = (*ppvsnNew)->Init(ptcsName, cbSize);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ;
}
return hr;
}
//+-------------------------------------------------------------------
//
// Function: PrivAtol
//
// Synopsis: Private "atol" function for better error control
//
// Arguments: [pszNum] - The number string
//
// [plResult] - A place to put the result
//
// Returns: S_OK if the function succeeds, another HRESULT otherwise
//
// History: 28-Jul-1995 AlexE Created
// 20-May-1996 Narindk Adapted for stgbase tests.
//
//--------------------------------------------------------------------
HRESULT PrivAtol(char *pszNum, LONG *plResult)
{
LONG l = 0 ;
*plResult = 0 ;
while (0 != *pszNum)
{
if (*pszNum > '9' || *pszNum < '0')
{
return E_INVALIDARG ;
}
l = 10 * l + (LONG) ((*pszNum - '0')) ;
pszNum++ ;
}
*plResult = l ;
return S_OK ;
}
//+-------------------------------------------------------------------------
//
// Function: GenerateRandomString
//
// Synopsis: Generates a random string using datagen object. This function
// differs from the orginal GenerateRandomFunction in the fact
// that it doesn't generate a random extenstion.
//
// Arguments: [pgdu] - Pointer to DG_UNICODE object.
// [pptszName] - Pointer to pointer to returned string.
// [ulMinLen] - Minimum length of string
// [ulMaxLen] - Maximum length of string
//
// Returns: HRESULT. S_OK if everything goes ok, error code otherwise.
//
// History: 17-Apr-96 NarindK Created.
// 31-July-96 Narindk Adapted to stgbase tests.
//
// Notes: BUGBUG: This function need to be enhance to handle different
// character sets.
// Please note that in GenerateRandomName, name gen may have an
// extension b/w 0 and FILEEXT_MAXLEN besides the length of name
// b/w ulMinLen and ulMax Len. But with this function, it will
// not have any extension, so the length would be b/w ulMinLen &
// ulMaxLen.
//
//--------------------------------------------------------------------------
HRESULT GenerateRandomString(
DG_STRING *pgds,
ULONG ulMinLen,
ULONG ulMaxLen,
LPTSTR *pptszName)
{
HRESULT hr = S_OK;
ULONG cTemp = 0;
USHORT usErr = 0;
ULONG ulActMaxLen = 0;
ULONG ulActMinLen = 0;
ULONG ulNameLen = 0;
LPTSTR ptszName = NULL;
LPWSTR pwszName = NULL;
TCHAR ptszFATCharSet[FAT_CHARSET_SIZE];
LPWSTR pwszFATCharSet = NULL;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("GenerateRandomString"));
DH_VDATEPTRIN(pgds, DG_STRING) ;
DH_VDATEPTROUT(pptszName, LPTSTR) ;
DH_ASSERT(NULL != pgds);
DH_ASSERT(NULL != pptszName);
if (S_OK == hr)
{
// Initialize out parameter.
*pptszName = NULL;
// Sanity check. Min length for name must be <= maximum length, if it
// isn't then make maximum length equal to minimum length.
if (ulMaxLen < ulMinLen)
{
ulMaxLen = ulMinLen;
}
// If Maximum length provided is 0, then default maximum length would
// be used. If Minimum length provided is zero, then 1 would be used
// for it.
// BUGBUG: We are using default maximum length for FAT system.
ulActMaxLen = (ulMaxLen == 0 ? DEF_FATNAME_MAXLEN : ulMaxLen);
ulActMinLen = (ulMinLen == 0 ? 1 : ulMinLen);
// '\0', '\', '/', and ':' are invalid for IStorage/IStream names
// (For doc file)
// '*', '"' '<' '>' '?' are invalid for IStorage/IStream names on OFS
// Initialize valid character set for FAT file names
_tcscpy(ptszFATCharSet, _TEXT("abcdefghijklmnopqrstuvwxyz"));
_tcscat(ptszFATCharSet, _TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
_tcscat(ptszFATCharSet, _TEXT("0123456789"));
// Call DataGen to generate a random file name
// BUGBUG: We are using FAT character set to generate random names.
#ifdef _MAC
usErr = pgds->Generate(
(UCHAR **)&ptszName, // force compiler to chose the right
(UCHAR *)ptszFATCharSet, // version of Generate
ulActMinLen,
ulActMaxLen);
#else
if(S_OK == hr)
{
// Convert TCHAR to WCHAR
hr = TStrToWStr(ptszFATCharSet, &pwszFATCharSet);
DH_HRCHECK(hr, TEXT("TStrToWStr")) ;
}
usErr = pgds->Generate(
&pwszName,
pwszFATCharSet,
ulActMinLen,
ulActMaxLen);
#endif //_MAC
if (usErr != DG_RC_SUCCESS) // DataGen error
{
hr = E_FAIL;
}
}
#ifndef _MAC
if(S_OK == hr)
{
// Convert WCHAR to TCHAR
hr = WStrToTStr(pwszName, &ptszName);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
}
#endif //_MAC
if (S_OK == hr)
{
ulNameLen = _tcslen(ptszName);
// Construct the full name
*pptszName = new TCHAR[ulNameLen + 1];
if(NULL == *pptszName)
{
hr = E_OUTOFMEMORY;
}
}
if (S_OK == hr)
{
_tcscpy(*pptszName, ptszName);
}
// Clean up
if (NULL != ptszName)
{
delete ptszName;
ptszName = NULL;
}
if (NULL != pwszName)
{
delete pwszName;
pwszName = NULL;
}
if (NULL != pwszFATCharSet)
{
delete pwszFATCharSet;
pwszFATCharSet = NULL;
}
return hr;
}
//+-------------------------------------------------------------------------
// Function: GenerateRandomStreamData
//
// Synopsis: Generates a random data using datagen object.
//
// Arguments: [pgds] - Pointer to DG_STRING object.
// [pptszName] - Pointer to pointer to returned string.
// [ulMinLen] - Minimum length of string
// [ulMaxLen] - Maximum length of string
//
// Returns: HRESULT. S_OK if everything goes ok, error code otherwise.
//
// History: 30-Mar-98 SCousens Created from GenerateRandomName
//
// Notes:
// -ulMaxLen is defaulted, so you dont need to specify
// both ulMinLen and ulMaxLen if you want a random buffer
// of a given length.
// -If ulMaxLen is less than ulMinLen, buffer will be
// ulMinLen bytes in length.
// -Generate a buffer upto CB_STMDATA_DATABUFFER bytes in
// length. Copy this buffer multiple times into actual
// returned buffer.
// -Alphabet currently ASCII 1-255
//--------------------------------------------------------------------------
HRESULT GenerateRandomStreamData(
DG_STRING *pgds,
LPTSTR *pptszData,
ULONG ulMinLen,
ULONG ulMaxLen)
{
HRESULT hr = S_OK;
UINT x;
USHORT usErr = 0;
ULONG cbBuffer = 0;
ULONG ulBufferLen = 0;
ULONG ulRndStart = 0;
ULONG ulBufStart = 0;
LPBYTE pbDataBuf = 0;
LPBYTE pbRndBuffer = 0;
DG_INTEGER *dgi; //we need to generate random numbers
#ifdef _MAC
CHAR szCharSet[CB_STMDATA_CHARSET];
#else
WCHAR szCharSet[CB_STMDATA_CHARSET];
#endif //_MAC
DH_FUNCENTRY (NULL, DH_LVL_DFLIB, TEXT("GenerateRandomStreamData"));
DH_VDATEPTRIN (pgds, DG_STRING) ;
DH_VDATEPTROUT (pptszData, LPTSTR) ;
DH_ASSERT (NULL != pgds);
DH_ASSERT (NULL != pptszData);
// use seed from given dgs, its the best we can do...
dgi = new DG_INTEGER (pgds->GetSeed ());
if (NULL == dgi)
{
hr = E_OUTOFMEMORY;
}
DH_HRCHECK (hr, TEXT("new DG_INTEGER"));
if (S_OK == hr)
{
// Initialize out parameter.
*pptszData = NULL;
// Sanity check. Min length for name must be <= maximum length.
// if used default params, make max same as min (it will be 0)
if (ulMaxLen < ulMinLen)
{
ulMaxLen = ulMinLen;
}
// If Maximum length provided is 0, then default to 512 (BUGBUG: hardcoded)
// If Minimum length provided is 0, then use 1
ulMaxLen = (ulMaxLen == 0 ? 512 : ulMaxLen);
ulMinLen = (ulMinLen == 0 ? 1 : ulMinLen);
// Initialize character set (BUGBUG currenly only ASCII 01-255)
for (x=0; x<CB_STMDATA_CHARSET-1; x++)
{
szCharSet[x] = x+1; //omit NULL to start
}
// this is how many chars we will be putting into the stream.
// since dg_string::Generate chooses, and we are bypassin that,
// we need to choose a number between ulminlen, ulmaxlen.
dgi->Generate (&ulBufferLen, ulMinLen, ulMaxLen);
// If needed buffer is smaller than our buffer,
// just generate that many bytes.
cbBuffer = min (CB_STMDATA_DATABUFFER, ulBufferLen);
// make our buffer
#ifdef _MAC
usErr = pgds->Generate(
(UCHAR **)&pbRndBuffer, // force compiler to chose the right
(UCHAR *)szCharSet, // version of Generate
cbBuffer / sizeof (TCHAR), // need chars
cbBuffer / sizeof (TCHAR)); // cbBuffer is bytes
#else
usErr = pgds->Generate(
(LPWSTR*)&pbRndBuffer,
szCharSet,
cbBuffer+1 / sizeof (TCHAR), // need chars
cbBuffer+1 / sizeof (TCHAR)); // cbBuffer is bytes
#endif //_MAC
if (usErr != DG_RC_SUCCESS) // DataGen error
{
hr = E_FAIL;
}
DH_HRCHECK (hr, TEXT("pgds::Generate"));
}
// now allocate the data buffer
if (S_OK == hr)
{
pbDataBuf = new BYTE[ulBufferLen];
if (NULL == pbDataBuf)
{
hr = E_OUTOFMEMORY;
}
DH_HRCHECK (hr, TEXT("new BYTE"));
DH_TRACE ((DH_LVL_TRACE4,
TEXT("Data buffer (%#x) - allocated %x bytes, (%d bytes)"),
pbDataBuf,
ulBufferLen,
ulBufferLen));
}
if (S_OK == hr)
{
for (ulBufStart=0; ulBufStart<ulBufferLen; ulBufStart+=cbBuffer)
{
//generate a random starting point
dgi->Generate (&ulRndStart,
0,
min (CB_STMDATA_DATABUFFER, ulBufferLen));
// Copy from rnd spot to end of buffer (provided we need it all)
cbBuffer = min (CB_STMDATA_DATABUFFER-ulRndStart, ulBufferLen-ulBufStart);
MoveMemory (&pbDataBuf[ulBufStart],
&pbRndBuffer[ulRndStart],
cbBuffer);
ulBufStart+=cbBuffer;
// Copy from begin of buffer to rnd spot (provided we need it)
cbBuffer = min (ulRndStart, ulBufferLen-ulBufStart);
if (0 != cbBuffer)
{
MoveMemory (&pbDataBuf[ulBufStart],
pbRndBuffer,
cbBuffer);
}
}
}
if (S_OK == hr)
{
*pptszData = (LPTSTR)pbDataBuf;
}
// Clean up
delete []pbRndBuffer;
return hr;
}
//-------------------------------------------------------------------------
// Function: ParseVirtualDFAndOpenAllSubStgsStms
//
// Synopsis: Given a storage, this function will recurse down the
// tree, opening all substorages and streams.
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode
// [dwStgMode] - Mode to open sub-storages
// [dwStmMode] - Mode to open streams
//
// Returns: HRESULT
//
// History: 27-January-97 SCousens Created.
//
// Notes: - provided VirtualCtrNode must already be open.
// - ALL substgs and stms must be closed before
// calling this, else access violations may occur
HRESULT ParseVirtualDFAndOpenAllSubStgsStms (VirtualCtrNode * pvcn,
DWORD dwStgMode,
DWORD dwStmMode)
{
HRESULT hr = S_OK;
VirtualCtrNode * pvcnTrav = NULL;
VirtualStmNode * pvsnTrav = NULL;
DH_VDATEPTRIN (pvcn, VirtualCtrNode);
DH_ASSERT (NULL != pvcn->GetIStoragePointer ()); //if not open _pstg will be null
// enumerate and open all stms in current stg.
pvsnTrav = pvcn->GetFirstChildVirtualStmNode ();
while(NULL != pvsnTrav && S_OK == hr)
{
if (NULL == pvsnTrav->GetIStreamPointer ())
{
hr = pvsnTrav->Open(NULL, dwStmMode, NULL);
}
pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode ();
}
// enumerate and open all stgs in current stg.
pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
while(NULL != pvcnTrav && S_OK == hr)
{
if (NULL == pvcnTrav->GetIStoragePointer ())
{
hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
}
// then recursively open all elements in just opened stg.
if (S_OK == hr)
{
hr = ParseVirtualDFAndOpenAllSubStgsStms (pvcnTrav,
dwStgMode,
dwStmMode);
}
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode ();
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: GetDocFileName
//
// Synopsis: Figures out name of docfile given the seed
//
// Arguments: [in] ulSeed - the seed value
// [out] ptszDocName - docfile name (needs to be deleted [])
//
// Returns: S_OK if all goes well, another HRESULT if not.
//
// History: 19-Mar-97 SCousens Created
//
// Notes: We can take advantage of the way VirtualDF gets the
// docfile name. Its the first string generated.
//
//--------------------------------------------------------------------------
HRESULT GetDocFileName (ULONG ulSeed, LPTSTR *pptszDocName)
{
HRESULT hr = E_FAIL;
DG_STRING *pdgs = NULL;
DH_FUNCENTRY(NULL, DH_LVL_TRACE1, TEXT("GetDocFileName"));
DH_VDATEPTROUT (pptszDocName, LPTSTR);
DH_ASSERT (NULL != ulSeed);
// init out stuff
*pptszDocName = NULL;
//get our datagen
pdgs = new DG_STRING (ulSeed);
if (NULL != pdgs)
{
// Generate random name for root
hr = GenerateRandomName(
pdgs,
MINLENGTH,
MAXLENGTH,
pptszDocName);
DH_HRCHECK (hr, TEXT("GenerateRandomName")) ;
}
// cleanup
delete pdgs;
return hr;
}
//-------------------------------------------------------------------------
// Function: CommitRandomVirtualCtrNodeStg
//
// Synopsis: Commits a VirtualCtrNode's IStorage and all ascedant
// IStorages. This traverses through all the parents
// and commit them excluding the root IStorage
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode whose IStorage
// is to be commited
// [grfCommitMode] - Commit mode
//
// Returns: HRESULT
//
// History: 16-Apr-97 BogdanT Created.
//
// Notes:
//--------------------------------------------------------------------------
HRESULT CommitRandomVirtualCtrNodeStg(VirtualCtrNode *pvcn,
DWORD grfCommitMode)
{
HRESULT hr = S_OK;
VirtualCtrNode *pvcnTrav = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("CommitRandomVirtualCtrNodeStg"));
DH_VDATEPTRIN(pvcn, PVCTRNODE) ;
DH_ASSERT(NULL != pvcn);
pvcnTrav = pvcn;
if(S_OK == hr)
{
while((NULL != pvcnTrav->GetParentVirtualCtrNode()) && (S_OK == hr))
{
hr = pvcnTrav->Commit(grfCommitMode);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Commit")) ;
pvcnTrav = pvcnTrav->GetParentVirtualCtrNode();
}
}
return hr;
}