[NeroCOM] Device enumaration bug

vbimport

#1

Nero API 6.3.1.10, SDK 1.05

I’ve got a strange bug in IEnumVARIANT implementation of INeroDrives.
The code:


#import "NeroCom.DLL" raw_interfaces_only named_guids

HRESULT DriveEnumCallback(IN VARIANT& varDrive)
{
	return S_OK;
}

void RefVariantClear(IN VARIANT& var)
{
	::VariantClear(&var);
}

template<class t_XXXX, class t_IEnumXXXX, class t_FnEnum, class t_FnRelease>
inline HRAPI EnumXXXX
	( IN t_IEnumXXXX *pEnumXXXX
	, IN t_FnEnum fnEnum
	, IN t_FnRelease fnRelease
	)
{
	ATLASSERT(pEnumXXXX);

	if (!pEnumXXXX)
		return E_INVALIDARG;

	t_XXXX				rgXXXX[64];
	ULONG				i;
	ULONG				nFetched;
	HRESULT				hr = S_OK;

	while (hr = pEnumXXXX->Next((ULONG)_countof(rgXXXX), rgXXXX, &nFetched), SUCCEEDED(hr) && nFetched)
	{
		ATLASSERT(nFetched <= (ULONG)_countof(rgXXXX));

		for (i = 0; i < nFetched; ++i)
		{
			hr = fnEnum(rgXXXX[i]);
			if (S_OK != hr)
				break; // abort

			fnRelease(rgXXXX[i]);
		}

		for (; i < nFetched; ++i)
		{
			// Release the rest in case of abort
			fnRelease(rgXXXX[i]);
		}

		// Fix the stupid bug in IDiaEnumSymbols::Next
		// Also avoid redundant call to t_IEnumXXXX::Next
		if (nFetched < _countof(rgXXXX) || S_OK != hr)
			break;
	}

	// S_OK if all data processed
	// S_FALSE if no data present (from pEnumXXXX::Next)
	// !S_OK if fnEnum returned anythig but S_OK
	return hr;
}

HRESULT EnumNeroDrives(IN NEROLib::INero2* pNero)
{
	ATL::CComPtr<NEROLib::INeroDrives>	pNeroDrives;
	ATL::CComPtr<IUnknown>				pNeroDrivesEnumUnk;
	ATL::CComPtr<IEnumVARIANT>			pNeroDrivesEnum;
	HRESULT								hr;

	hr = pNero->GetDrives(NEROLib::NERO_MEDIA_DVD_ROM, &pNeroDrives);
	if (SUCCEEDED(hr))
		hr = pNeroDrives->get__NewEnum(&pNeroDrivesEnumUnk);
	if (SUCCEEDED(hr))
		hr = pNeroDrivesEnumUnk->QueryInterface(&pNeroDrivesEnum);
	if (SUCCEEDED(hr))
		hr = EnumXXXX<VARIANT>(pNeroDrivesEnum.p, DriveEnumCallback, RefVariantClear);

	return hr;
}

HRESULT TestNero()
{
	ATL::CComPtr<NEROLib::INero2>		pNero;
	HRESULT								hr;
	short								majhi, majlo, minhi, minlo;


	hr = pNero.CoCreateInstance(NEROLib::CLSID_Nero);
	if (SUCCEEDED(hr))
	{
		hr = pNero->APIVersion(&majhi, &majlo, &minhi, &minlo);
		if (SUCCEEDED(hr))
		{
			_tprintf(_T("Using Nero API %u.%u.%u.%u
"), majhi, majlo, minhi, minlo);

			hr = EnumNeroDrives(pNero);
		}
	}

	return hr;
}

The bug found in EnumXXXX<>, at line


	while (hr = pEnumXXXX->Next((ULONG)_countof(rgXXXX), rgXXXX, &nFetched), SUCCEEDED(hr) && nFetched)


When size of rgXXXX array is bigger then 1, IEnumVARIANT failed with
result code E_INVALIDARG.
For me, it looks like IEnumVARIANT implementation of INeroDrives can NOT return more then ONE item per call.

Please, let me know is it a bug or well-know “feature”?

-Paul


#2

Sorry, this is by design. You can enumerate one device at a time. It should perhaps copy one item and still return S_OK and 1 in nFetched. The behavior will be changed for the next release.