windows-nt/Source/XPSP1/NT/com/oleutest/cachetst/multi.cpp
2020-09-26 16:20:57 +08:00

288 lines
6.8 KiB
C++

//+----------------------------------------------------------------------------
//
// File:
// multi.cpp
//
// Contents:
// Cache node test which creates multiple nodes, then performs
// various data tests on them.
//
// History:
//
// 04-Sep-94 davepl Created
//
//-----------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
//+----------------------------------------------------------------------------
//
// Member: TestInstance::MultiCache
//
// Synopsis: Caches N unique nodes, where N is large (>100). Saves
// the cache, then reloads it to compare.
//
// Arguments: [dwCount] Number of new nodes to cache
//
// Returns: HRESULT
//
// Notes:
//
// History: 24-Aug-94 Davepl Created
//
//-----------------------------------------------------------------------------
HRESULT TestInstance::MultiCache(DWORD dwCount)
{
HRESULT hr;
DWORD iCFGEN = 0,
iNODES = 0,
iSDATA = 0;
TraceLog Log(NULL, "TestInstance::MultiCache", GS_CACHE, VB_MINIMAL);
Log.OnEntry (" ( %d )\n", dwCount);
Log.OnExit (" ( %X )\n", &hr);
//
// A temporary buffer for creating text clipformat names
//
char szFormatName[ MAX_BUF ];
//
// An array of UINTs to hold our private clipformats, and an
// array of DWORDS to hold the connection IDs
//
CLIPFORMAT *acfArray = (CLIPFORMAT *) malloc(dwCount * sizeof(CLIPFORMAT));
if (NULL == acfArray)
{
return E_OUTOFMEMORY;
}
DWORD *adwConnections = (DWORD *) malloc(dwCount * sizeof(DWORD));
if (NULL == adwConnections)
{
free(acfArray);
return E_OUTOFMEMORY;
}
//
// Generate N private clipformats
//
for (iCFGEN=0; iCFGEN < dwCount; iCFGEN++)
{
sprintf(szFormatName, "LocalFormat%d", iCFGEN);
acfArray[iCFGEN] = (WORD) RegisterClipboardFormat(szFormatName);
if (0 == acfArray[iCFGEN])
{
free(acfArray);
return HRESULT_FROM_WIN32(GetLastError());
}
}
//
// Cache N nodes based on those formats
//
FORMATETC fetc =
{
0, // Clipformat
NULL, // DVTargetDevice
DVASPECT_CONTENT, // Aspect
-1, // Index
TYMED_HGLOBAL // TYMED
};
STGMEDIUM stgm;
for (iNODES = 0; iNODES < dwCount; iNODES++)
{
fetc.cfFormat = acfArray[iNODES];
hr = m_pOleCache->Cache(&fetc, ADVF_PRIMEFIRST, &adwConnections[iNODES]);
// We are expecting the cache to return CACHE_S_FORMATETC_NOTSUPPORTED
// for this data, since it cannot draw it.
hr = MassageErrorCode(CACHE_S_FORMATETC_NOTSUPPORTED, hr);
if (S_OK != hr)
{
break;
}
}
//
// If all went well adding the nodes, proceed to SetData into
// each of the nodes with some unique data
//
if (S_OK == hr)
{
for (iSDATA = 0; iSDATA < dwCount; iSDATA++)
{
HGLOBAL hTmp = GlobalAlloc(GMEM_MOVEABLE, sizeof(DWORD));
if (NULL == hTmp)
{
break;
}
DWORD * pdw = (DWORD *) GlobalLock(hTmp);
if (NULL == pdw)
{
GlobalFree(hTmp);
break;
}
//
// Set the data in the HGLOBAL equal to the clipformat
// for this node
//
*pdw = iSDATA;
GlobalUnlock(hTmp);
stgm.tymed = TYMED_HGLOBAL;
stgm.hGlobal = hTmp;
fetc.cfFormat = acfArray[iSDATA];
hr = m_pOleCache->SetData(&fetc, &stgm, TRUE /* fRelease */);
if (S_OK != hr)
{
break;
}
}
}
//
// Save the cache and reload it
//
if (S_OK == hr)
{
hr = SaveAndReload();
}
//
// Just to make things interesting, let's DiscardCache before we
// start looking for data. This will force the cache to demand-load
// the data as we ask for it. Since we know the cache is not dirty,
// there's no value (practical or from a test perspective) in asking
// the DiscardCache to save along the way.
//
if (S_OK == hr)
{
hr = m_pOleCache2->DiscardCache(DISCARDCACHE_NOSAVE);
}
if (S_OK == hr)
{
for (iSDATA = 0; iSDATA < dwCount; iSDATA++)
{
//
// For each of the cache nodes we added, try to
// get the data that was saved in the cache under
// that clipformat
//
fetc.cfFormat = acfArray[iSDATA];
hr = m_pDataObject->GetData(&fetc, &stgm);
if (S_OK != hr)
{
ReleaseStgMedium(&stgm);
break;
}
//
// Lock the HGLOBAL and compare what is in the cache
// node to what we expect should be there (the index
// into our clipboard format table
//
DWORD * pdw = (DWORD *) GlobalLock(stgm.hGlobal);
if (NULL == pdw)
{
hr = E_OUTOFMEMORY;
break;
}
if (*pdw != iSDATA)
{
hr = E_FAIL;
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
break;
}
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
}
}
//
// We want to remove all of the cache nodes we have added.
// Unforunately, there is no easy way to do this; we have to
// enumerate over the cache and toss nodes as we find them, even
// though we _know_ everything about the nodes. Sigh...
//
//
// Get an enumerator on the cache
//
LPENUMSTATDATA pEsd;
if (S_OK == hr)
{
hr = m_pOleCache->EnumCache(&pEsd);
}
//
// Since we've got a large number of cache nodes in the cache,
// now is a perfect time to run the generic enumerator tests on
// the cache.
//
if (S_OK == hr)
{
hr = TestEnumerator((void *) pEsd, sizeof(STATDATA), iSDATA, NULL, NULL,NULL);
}
//
// Reset the enumerator before beginning our UnCache loop.
//
if (S_OK == hr)
{
hr = pEsd->Reset();
}
if (S_OK == hr)
{
//
// Loop until a failure or until we have removed all of
// the nodes that we thought should exist
//
STATDATA stat;
while (S_OK == hr && iSDATA > 0)
{
hr = pEsd->Next(1, &stat, NULL);
if (S_OK == hr)
{
hr = m_pOleCache->Uncache(stat.dwConnection);
iSDATA--;
}
}
}
return hr;
}