// wait for the next request to complete
HRESULT
CAsyncIo::WaitForNext(
DWORD dwTimeout,
LPVOID * ppContext,
DWORD * pdwUser,
LONG * pcbActual)
{
CheckPointer(ppContext,E_POINTER);
CheckPointer(pdwUser,E_POINTER);
CheckPointer(pcbActual,E_POINTER);
// some errors find a sample, others don't. Ensure that
// *ppContext is NULL if no sample found
*ppContext = NULL;
// wait until the event is set, but since we are not
// holding the critsec when waiting, we may need to re-wait
for(;;)
{
if(!m_evDone.Wait(dwTimeout))
{
// timeout occurred
return VFW_E_TIMEOUT;
}
// get next event from list
CAsyncRequest* pRequest = GetDoneItem();
if(pRequest)
{
// found a completed request
// check if ok
HRESULT hr = pRequest->GetHResult();
if(hr == S_FALSE)
{
// this means the actual length was less than
// requested - may be ok if he aligned the end of file
if((pRequest->GetActualLength() +
pRequest->GetStart()) == Size())
{
hr = S_OK;
}
else
{
// it was an actual read error
hr = E_FAIL;
}
}
// return actual bytes read
*pcbActual = pRequest->GetActualLength();
// return his context
*ppContext = pRequest->GetContext();
*pdwUser = pRequest->GetUser();
delete pRequest;
return hr;
}
else
{
// Hold the critical section while checking the list state
CAutoLock lck(&m_csLists);
if(m_bFlushing && !m_bWaiting)
{
// can't block as we are between BeginFlush and EndFlush
// but note that if m_bWaiting is set, then there are some
// items not yet complete that we should block for.
return VFW_E_WRONG_STATE;
}
}
// done item was grabbed between completion and
// us locking m_csLists.
}
}