HRESULT CAsyncIo::WaitForNext( DWORD dwTimeout, LPVOID *ppContext, DWORD * pdwUser, LONG* pcbActual) { *ppContext = NULL; for (;;) { if (!m_evDone.Wait(dwTimeout)) { return VFW_E_TIMEOUT; } CAsyncRequest* pRequest = GetDoneItem(); if (pRequest) { HRESULT hr = pRequest->GetHResult(); if (hr == S_FALSE) { if ((pRequest->GetActualLength() + pRequest->GetStart()) == Size()) { hr = S_OK; } else { hr = E_FAIL; } } *pcbActual = pRequest->GetActualLength(); *ppContext = pRequest->GetContext(); *pdwUser = pRequest->GetUser(); delete pRequest; return hr; } else { CAutoLock lck(&m_csLists); if (m_bFlushing && !m_bWaiting) { return VFW_E_WRONG_STATE; } } } }
// wait for the next request to complete HRESULT CAsyncIo::WaitForNext( DWORD dwTimeout, LPVOID * ppContext, DWORD_PTR * 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) { LONGLONG llBytesToRead = 0, llAvailable = 0; hr = m_pStream->Length(&llBytesToRead, &llAvailable); if (SUCCEEDED(hr) && (pRequest->GetActualLength() + pRequest->GetStart() == llBytesToRead)) { // this means the actual length was less than // requested - may be ok if he aligned the end of file 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. } }