HRESULT nsScriptablePeer::GetIDispatch(IDispatch **pdisp) { if (pdisp == NULL) { return E_INVALIDARG; } *pdisp = NULL; IUnknownPtr unk; HRESULT hr = mPlugin->pControlSite->GetControlUnknown(&unk); if (unk.GetInterfacePtr() == NULL) { return E_FAIL; } IDispatchPtr disp = unk; if (disp.GetInterfacePtr() == NULL) { return E_FAIL; } *pdisp = disp.GetInterfacePtr(); (*pdisp)->AddRef(); return S_OK; }
STDMETHODIMP WMFByteStream::EndRead(IMFAsyncResult* aResult, ULONG *aBytesRead) { NS_ENSURE_TRUE(aResult, E_POINTER); NS_ENSURE_TRUE(aBytesRead, E_POINTER); ReentrantMonitorAutoEnter mon(mReentrantMonitor); // Extract our state object. IUnknownPtr unknown; HRESULT hr = aResult->GetObject(&unknown); if (FAILED(hr) || !unknown) { return E_INVALIDARG; } AsyncReadRequestState* requestState = static_cast<AsyncReadRequestState*>(unknown.GetInterfacePtr()); // Important: Only advance the read cursor if the caller hasn't seeked // since it called BeginRead(). If it has seeked, we still must report // the number of bytes read (in *aBytesRead), but we don't advance the // read cursor; reads performed after the seek will do that. The SourceReader // caller seems to keep track of which async read requested which range // to be read, and does call SetCurrentPosition() before it calls EndRead(). if (mOffset == requestState->mOffset) { mOffset += requestState->mBytesRead; } // Report result. *aBytesRead = requestState->mBytesRead; LOG("WMFByteStream::EndRead() offset=%lld *aBytesRead=%u mOffset=%lld hr=0x%x eof=%d", requestState->mOffset, *aBytesRead, mOffset, hr, (mOffset == mResource->GetLength())); return S_OK; }
// IMFAsyncCallback::Invoke implementation. This is called back on the work // queue thread, and performs the actual read. STDMETHODIMP WMFByteStream::Invoke(IMFAsyncResult* aResult) { // Note: We assume that the WMF Work Queue that calls this function does // so synchronously, i.e. this function call returns before any other // work queue item runs. This is important, as if we run multiple instances // of this function at once we'll interleave seeks and reads on the // media resoure. // Extract the caller's IMFAsyncResult object from the wrapping aResult object. IMFAsyncResultPtr callerResult; IUnknownPtr unknown; HRESULT hr = aResult->GetState(&unknown); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); callerResult = unknown; NS_ENSURE_TRUE(callerResult, E_FAIL); // Get the object that holds our state information for the asynchronous call. hr = callerResult->GetObject(&unknown); NS_ENSURE_TRUE(SUCCEEDED(hr) && unknown, hr); AsyncReadRequestState* requestState = static_cast<AsyncReadRequestState*>(unknown.GetInterfacePtr()); // Ensure the read head is at the correct offset in the resource. It may not // be if the SourceReader seeked. if (mResource->Tell() != requestState->mOffset) { nsresult rv = mResource->Seek(nsISeekableStream::NS_SEEK_SET, requestState->mOffset); if (NS_FAILED(rv)) { // Let SourceReader know the read failed. callerResult->SetStatus(E_FAIL); wmf::MFInvokeCallback(callerResult); LOG("WMFByteStream::Invoke() seek to read offset failed, aborting read"); return S_OK; } } NS_ASSERTION(mResource->Tell() == requestState->mOffset, "State mismatch!"); // Read in a loop to ensure we fill the buffer, when possible. ULONG totalBytesRead = 0; nsresult rv = NS_OK; while (totalBytesRead < requestState->mBufferLength) { BYTE* buffer = requestState->mBuffer + totalBytesRead; ULONG bytesRead = 0; ULONG length = requestState->mBufferLength - totalBytesRead; rv = mResource->Read(reinterpret_cast<char*>(buffer), length, reinterpret_cast<uint32_t*>(&bytesRead)); totalBytesRead += bytesRead; if (NS_FAILED(rv) || bytesRead == 0) { break; } } // Record the number of bytes read, so the caller can retrieve // it later. requestState->mBytesRead = NS_SUCCEEDED(rv) ? totalBytesRead : 0; callerResult->SetStatus(S_OK); LOG("WMFByteStream::Invoke() read %d at %lld finished rv=%x", requestState->mBytesRead, requestState->mOffset, rv); // Let caller know read is complete. wmf::MFInvokeCallback(callerResult); return S_OK; }