442 lines
9.6 KiB
C++
442 lines
9.6 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
TestIWiaEnumXXX.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Hakki T. Bostanci (hakkib) 06-Apr-2000
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
//
|
||
|
// This is not a real .cpp module, it is meant to be included in .h
|
||
|
//
|
||
|
|
||
|
#ifdef DEFINE_TEMPLATES
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
|
||
|
template <class> struct storage_traits { };
|
||
|
|
||
|
template <> struct storage_traits<CComPtr<IEnumWIA_DEV_INFO> > { typedef CIWiaPropertyStoragePtr storage_type; };
|
||
|
template <> struct storage_traits<CComPtr<IEnumWIA_DEV_CAPS> > { typedef CWiaDevCap storage_type; };
|
||
|
template <> struct storage_traits<CComPtr<IEnumWIA_FORMAT_INFO> > { typedef CWiaFormatInfo storage_type; };
|
||
|
template <> struct storage_traits<CComPtr<IEnumWiaItem> > { typedef CIWiaItemPtr storage_type; };
|
||
|
template <> struct storage_traits<CComPtr<CMyEnumSTATPROPSTG> > { typedef CStatPropStg storage_type; };
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
|
||
|
template <class interface_type>
|
||
|
void TestEnum(interface_type &pEnum, PCTSTR pInterfaceName)
|
||
|
{
|
||
|
m_pszContext = pInterfaceName;
|
||
|
|
||
|
TestGetCount(pEnum);
|
||
|
TestReset(pEnum);
|
||
|
TestNext(pEnum);
|
||
|
TestSkip(pEnum);
|
||
|
TestClone(pEnum);
|
||
|
|
||
|
m_pszContext = 0;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
|
||
|
template <class interface_type>
|
||
|
void TestNext(interface_type &pEnum)
|
||
|
{
|
||
|
typedef storage_traits<interface_type>::storage_type storage_type;
|
||
|
|
||
|
ULONG nItems = -1;
|
||
|
|
||
|
CHECK_HR(pEnum->GetCount(&nItems));
|
||
|
|
||
|
if (nItems == 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// try to get items; first, last, all, one more than all, past the last
|
||
|
|
||
|
SubTestNext(pEnum, 0, 1, 1, S_OK);
|
||
|
|
||
|
SubTestNext(pEnum, nItems-1, 1, 1, S_OK);
|
||
|
|
||
|
SubTestNext(pEnum, 0, nItems, nItems, S_OK);
|
||
|
|
||
|
SubTestNext(pEnum, 0, nItems+1, nItems, S_FALSE);
|
||
|
|
||
|
SubTestNext(pEnum, nItems-1, 2, 1, S_FALSE);
|
||
|
|
||
|
//SubTestNext(pEnum, nItems, 1, 0, S_FALSE);
|
||
|
|
||
|
//SubTestNext(pEnum, 0, nItems, UINT_MAX, nItems);
|
||
|
|
||
|
// try to pass 0 for celtFetched,
|
||
|
// this should be allowed when fetching one item
|
||
|
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
CCppMem<storage_type> pOneItem(1);
|
||
|
|
||
|
LOG_HR(pEnum->Next(1, &pOneItem[0], 0), == S_OK);
|
||
|
|
||
|
if (m_bRunBadParamTests)
|
||
|
{
|
||
|
// try to pass 0 for celtFetched,
|
||
|
// this should not be allowed when fetching more than one item
|
||
|
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
CCppMem<storage_type> pTwoItems(2);
|
||
|
|
||
|
LOG_HR(pEnum->Next(2, &pTwoItems[0], 0), != S_OK);
|
||
|
|
||
|
// try to pass 0 for the element array
|
||
|
// this should not be allowed
|
||
|
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
ULONG nFetched = -1;
|
||
|
|
||
|
LOG_HR(pEnum->Next(0, 0, &nFetched), != S_OK);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
|
||
|
template <class interface_type>
|
||
|
void
|
||
|
SubTestNext(
|
||
|
interface_type &pEnum,
|
||
|
ULONG nToBeSkipped,
|
||
|
ULONG nAskedToBeFetched,
|
||
|
ULONG nExpectedToBeFetched,
|
||
|
HRESULT hrExpected
|
||
|
)
|
||
|
{
|
||
|
typedef storage_traits<interface_type>::storage_type storage_type;
|
||
|
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
if (nToBeSkipped)
|
||
|
{
|
||
|
CHECK_HR(pEnum->Skip(nToBeSkipped));
|
||
|
}
|
||
|
|
||
|
CCppMem<storage_type> pItems(nAskedToBeFetched);
|
||
|
ULONG nFetched = -1;
|
||
|
|
||
|
HRESULT hrAPI = pEnum->Next(nAskedToBeFetched, &pItems[0], &nFetched);
|
||
|
|
||
|
if (hrAPI != hrExpected)
|
||
|
{
|
||
|
LOG_ERROR(
|
||
|
_T("pEnum->Next(%d, &pItems[0], &nFetched) == %s, expected %s"),
|
||
|
nAskedToBeFetched,
|
||
|
(PCTSTR) HResultToStr(hrAPI),
|
||
|
(PCTSTR) HResultToStr(hrExpected)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
LOG_CMP(nFetched, ==, nExpectedToBeFetched);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
|
||
|
template <class interface_type>
|
||
|
void TestReset(interface_type &pEnum)
|
||
|
{
|
||
|
typedef storage_traits<interface_type>::storage_type storage_type;
|
||
|
|
||
|
ULONG nItems = -1;
|
||
|
|
||
|
CHECK_HR(pEnum->GetCount(&nItems));
|
||
|
|
||
|
if (nItems == 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// reset and read the first element
|
||
|
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
if (!m_bBVTMode)
|
||
|
{
|
||
|
storage_type FirstItemBeforeQueryingAll;
|
||
|
CHECK_HR(pEnum->Next(1, &FirstItemBeforeQueryingAll, 0));
|
||
|
|
||
|
// go to the last item
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
storage_type Item;
|
||
|
hr = pEnum->Next(1, &Item, 0);
|
||
|
}
|
||
|
while (hr == S_OK);
|
||
|
|
||
|
// reset the enumerator and read the first element again
|
||
|
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
storage_type FirstItemAfterQueryingAll;
|
||
|
CHECK_HR(pEnum->Next(1, &FirstItemAfterQueryingAll, 0));
|
||
|
|
||
|
if (FirstItemBeforeQueryingAll != FirstItemAfterQueryingAll)
|
||
|
{
|
||
|
LOG_ERROR(_T("FirstItemBeforeQueryingAll != FirstItemAfterQueryingAll"));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
|
||
|
template <class interface_type>
|
||
|
void TestSkip(interface_type &pEnum)
|
||
|
{
|
||
|
typedef storage_traits<interface_type>::storage_type storage_type;
|
||
|
|
||
|
// get the item count
|
||
|
|
||
|
ULONG nItems = -1;
|
||
|
|
||
|
CHECK_HR(pEnum->GetCount(&nItems));
|
||
|
|
||
|
if (nItems == 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// read and store each item
|
||
|
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
CCppMem<storage_type> pItems(nItems);
|
||
|
|
||
|
for (int i = 0; i < nItems; ++i)
|
||
|
{
|
||
|
CHECK_HR(pEnum->Next(1, &pItems[i], 0));
|
||
|
}
|
||
|
|
||
|
// test valid cases
|
||
|
|
||
|
for (int nToBeSkipped = 0; nToBeSkipped < nItems; ++nToBeSkipped)
|
||
|
{
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
for (int nItem = nToBeSkipped; nItem < nItems; nItem += nToBeSkipped + 1)
|
||
|
{
|
||
|
CHECK_HR(pEnum->Skip(nToBeSkipped));
|
||
|
|
||
|
storage_type Item;
|
||
|
|
||
|
CHECK_HR(pEnum->Next(1, &Item, 0));
|
||
|
|
||
|
if (Item != pItems[nItem])
|
||
|
{
|
||
|
LOG_ERROR(_T("Item != pItems[nItem] after skipping %d"), nToBeSkipped);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// test invalid cases
|
||
|
|
||
|
if (m_bRunBadParamTests)
|
||
|
{
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
LOG_HR(pEnum->Skip(nItems+1), == S_FALSE);
|
||
|
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
LOG_HR(pEnum->Skip(-1), == S_FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
|
||
|
template <class interface_type>
|
||
|
void TestClone(interface_type &pEnum, bool bRecurse = true)
|
||
|
{
|
||
|
typedef storage_traits<interface_type>::storage_type storage_type;
|
||
|
|
||
|
// make the clone
|
||
|
|
||
|
interface_type pClone;
|
||
|
|
||
|
if (LOG_HR(pEnum->Clone(&pClone), == S_OK) && !m_bBVTMode)
|
||
|
{
|
||
|
// reset both the original and the clone enumerators, then iterate
|
||
|
// through each element one by one and compare them
|
||
|
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
CHECK_HR(pClone->Reset());
|
||
|
|
||
|
HRESULT hr, hr1, hr2;
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
// also, make a clone of the current state and check that
|
||
|
// the state is captured in the clone
|
||
|
|
||
|
interface_type pClone2;
|
||
|
CHECK_HR(pEnum->Clone(&pClone2));
|
||
|
|
||
|
// get the next item from the original interface
|
||
|
|
||
|
storage_type Item;
|
||
|
|
||
|
hr = pEnum->Next(1, &Item, 0);
|
||
|
|
||
|
// get the next item from the first clone
|
||
|
|
||
|
storage_type Item1;
|
||
|
|
||
|
hr1 = pClone->Next(1, &Item1, 0);
|
||
|
|
||
|
// get the next item from the second clone
|
||
|
|
||
|
storage_type Item2;
|
||
|
|
||
|
hr2 = pClone2->Next(1, &Item2, 0);
|
||
|
|
||
|
if (hr != S_OK || hr1 != S_OK || hr2 != S_OK)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (Item != Item1 || Item1 != Item2)
|
||
|
{
|
||
|
LOG_ERROR(_T("Clone states are not equal"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (hr != S_FALSE || hr1 != S_FALSE || hr2 != S_FALSE)
|
||
|
{
|
||
|
LOG_ERROR(_T("After enumeration, clone states are not equal"));
|
||
|
}
|
||
|
|
||
|
// test the clone
|
||
|
|
||
|
TestNext(pClone);
|
||
|
|
||
|
TestReset(pClone);
|
||
|
|
||
|
TestSkip(pClone);
|
||
|
|
||
|
if (bRecurse)
|
||
|
{
|
||
|
TestClone(pClone, false);
|
||
|
}
|
||
|
|
||
|
TestGetCount(pClone);
|
||
|
}
|
||
|
|
||
|
// test bad param
|
||
|
|
||
|
if (m_bRunBadParamTests)
|
||
|
{
|
||
|
LOG_HR(pEnum->Clone(0), != S_OK);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
|
||
|
template <class interface_type>
|
||
|
void TestGetCount(interface_type &pEnum)
|
||
|
{
|
||
|
typedef storage_traits<interface_type>::storage_type storage_type;
|
||
|
|
||
|
// First, get the item count using GetCount()
|
||
|
|
||
|
ULONG cItemsFromGetCount = 0;
|
||
|
|
||
|
if (LOG_HR(pEnum->GetCount(&cItemsFromGetCount), == S_OK) && !m_bBVTMode)
|
||
|
{
|
||
|
// Now, find the item count by first resetting the enumerator
|
||
|
// and then querying for each item one by one using Next()
|
||
|
|
||
|
ULONG cItemsFromNext = 0;
|
||
|
|
||
|
CHECK_HR(pEnum->Reset());
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// verify that GetCount returns the same result after a Next or Reset
|
||
|
|
||
|
ULONG cItemsFromGetCountNow = 0;
|
||
|
|
||
|
LOG_HR(pEnum->GetCount(&cItemsFromGetCountNow), == S_OK);
|
||
|
|
||
|
LOG_CMP(cItemsFromGetCountNow, ==, cItemsFromGetCount);
|
||
|
|
||
|
// get the next item
|
||
|
|
||
|
storage_type Item;
|
||
|
ULONG cFetched = 0;
|
||
|
|
||
|
hr = pEnum->Next(1, &Item, &cFetched);
|
||
|
|
||
|
cItemsFromNext += cFetched;
|
||
|
}
|
||
|
while (hr == S_OK);
|
||
|
|
||
|
LOG_HR(hr, == S_FALSE);
|
||
|
|
||
|
// verify that the two counts are equal
|
||
|
|
||
|
LOG_CMP(cItemsFromNext, ==, cItemsFromGetCount);
|
||
|
}
|
||
|
|
||
|
// test bad param
|
||
|
|
||
|
if (m_bRunBadParamTests)
|
||
|
{
|
||
|
LOG_HR(pEnum->GetCount(0), != S_OK);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif //DEFINE_TEMPLATES
|