📄 memfsys.cpp
字号:
*/ if (m_ulFlags == ulFlags || ulFlags == 0) { m_ulPos = 0; m_pFileResponse->InitDone(HXR_OK); return HXR_OK; } _CloseFile(); } UpdateFileNameMember(); m_bAsynchInit = FALSE; m_ulFlags = ulFlags; BOOL bExists = FALSE; IHXMemoryFileSystem* pMemFS = GetMemoryFileSystem(); IHXMemoryFileSystem2* pMemFS2 = NULL; if (pMemFS) { bExists = pMemFS->Exists(m_pFilename); if (!bExists) { // XXXNH: we have to flag this *before* we request the file, or // else initialization will fail with a synchronous file system m_bAsynchInit = TRUE; bChoseAsynchInit = TRUE; pMemFS2 = GetMemoryFileSystem2(); if (pMemFS2) { // try to request the file lReturnVal = pMemFS2->RequestURL(m_pFilename, this); } else { //XXXNH: No IHXMemoryFileSystem2? this should never happen! HX_ASSERT(FALSE); lReturnVal = HXR_FAIL; } // request failed, so respond with a failure if (lReturnVal != HXR_OK) { m_pFileResponse->InitDone(HXR_DOC_MISSING); lReturnVal = HXR_DOC_MISSING; // XXXNH: we're already initialized: we are missing! m_bAsynchInit = FALSE; bChoseAsynchInit = FALSE; goto exit; } } } else { // XXXNH: No IHXMemoryFileSystem? this should never happen! HX_ASSERT(FALSE); m_pFileResponse->InitDone(HXR_FAIL); return HXR_FAIL; } // XXXNH: it is entirely possible that if we're initializing // asynchronously that we may have been closed as a result of making the // URL request! if (!m_bClosed && !bChoseAsynchInit) { if (!m_pCommonClassFactory) { HX_ASSERT(m_pContext); m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void **)&m_pCommonClassFactory); } if (m_pRequest && SUCCEEDED(m_pRequest->QueryInterface( IID_IHXRequestContext, (void**)&pIHXRequestContextCurrent))) { pIHXRequestContextCurrent->GetUserContext(pIUnknownUserContext); HX_RELEASE(pIHXRequestContextCurrent); } if (!bChoseAsynchInit) { lReturnVal = _OpenFile(ulFlags); HX_RESULT status = m_pChunkyRes ? HXR_OK : HXR_DOC_MISSING; resultInitDone = m_pFileResponse->InitDone(status); } }exit: HX_RELEASE(pIUnknownUserContext); HX_RELEASE(pMemFS); HX_RELEASE(pMemFS2); return (HXR_OK==lReturnVal? resultInitDone:lReturnVal);}/************************************************************************ * Method: * IHXFileObject::GetFilename * Purpose: * Returns the filename (without any path information) associated * with a file object. */STDMETHODIMP CMemoryFileObject::GetFilename( REF(const char*) /*OUT*/ pFilename){ UpdateFileNameMember(); // Find the separator character before the file name pFilename = ::strrchr(m_pFilename, '/'); if (pFilename != NULL) // Found { // File name starts after the separator charactor pFilename++; } else // Not found { pFilename = m_pFilename; } return HXR_OK;}/************************************************************************ * Method: * IHXFileObject::Close * Purpose: * Closes the file resource and releases all resources associated * with the object. */STDMETHODIMP CMemoryFileObject::Close(){ m_bClosed = TRUE; if (m_bAsynchInit) { m_bAsynchInit = FALSE; IHXMemoryFileSystem2* pFS = GetMemoryFileSystem2(); if (pFS) { pFS->CancelRequest(m_pFilename, HXR_FAIL); } } // If there is a pending callback, be sure to remove it! if (m_pCallback && m_pCallback->m_ulPendingCallbackID && m_pScheduler) { m_pScheduler->Remove(m_pCallback->m_ulPendingCallbackID); } HX_RELEASE(m_pCallback); HX_RELEASE(m_pScheduler); if (m_pContext) { m_pContext->Release(); m_pContext = NULL; } if (m_pCommonClassFactory) { m_pCommonClassFactory->Release(); m_pCommonClassFactory = NULL; } if (m_pFileSystem) { m_pFileSystem->Release(); m_pFileSystem = NULL; } if (m_pRequest) { m_pRequest->Release(); m_pRequest = NULL; } if (m_pChunkyRes) { _CloseFile(); } if(m_pFilename) { delete[] m_pFilename; m_pFilename = NULL; } // It is vitally important that the CloseDone be the last step in // this method, as the last reference to this object may be // released inside CloseDone! Do not place code after this if block! // // XXXGH...can't release the m_pFileResponse because it's needed here, // so I've moved the m_pFileResponse->Release() to after the // CloseDone() call and added an AddRef()/Release() pair if (!m_bLocalClose) { AddRef(); if(m_pFileResponse) { m_pFileResponse->CloseDone(HXR_OK); m_pFileResponse->Release(); m_pFileResponse = NULL; } Release(); } else if (m_pFileResponse) { m_pFileResponse->Release(); m_pFileResponse = NULL; } return HXR_OK;}/************************************************************************ * Method: * IHXFileObject::Read * Purpose: * Reads a buffer of data of the specified length from the file * and asynchronously returns it to the caller via the * IHXFileResponse interface passed in to Init. */STDMETHODIMP CMemoryFileObject::Read(ULONG32 ulCount){ HX_ASSERT(m_pFileResponse); // XXXBHG, For now, you cant read more than 1MB at a time! if (ulCount > 0x000FFFFF) { HX_ASSERT(!"CMemoryFileObject::Read() - ulCount > 0xFFFFF"); //Force the system to recognize a failed Read so infinite // buffering does not occur with the core waiting for EOF: m_pFileResponse->ReadDone(HXR_FAIL, NULL); return HXR_INVALID_PARAMETER; } if (m_bSeekPending) { m_pFileResponse->ReadDone(HXR_SEEK_PENDING, NULL); return HXR_UNEXPECTED; } if(!m_pChunkyRes && m_bCanBeReOpened) { _OpenFile(m_ulFlags); m_bCanBeReOpened = FALSE; } if (m_pChunkyRes) { if(!(m_ulFlags & HX_FILE_READ)) return HXR_UNEXPECTED; // Do we have enough data? ULONG32 ulCurLen = m_pStatus->GetSize(); if (ulCount + m_ulPos > ulCurLen) { // If we're done filling the memory file, read the remainder if (m_pStatus->GetDone()) { /* Read the last few bytes */ if (m_ulPos < ulCurLen) { ulCount = ulCurLen - m_ulPos; } else { m_bInReadDone = TRUE; // Let the file response sink know about the buffer... HX_RESULT result = HXR_FAIL; m_pFileResponse->ReadDone(result, NULL); m_bInReadDone = FALSE; return result; } } else { // Request that the context read some more data for us. IHXMemoryFileContext* pCtxt = m_pStatus->GetContext(); if (pCtxt) { pCtxt->RequestRead(m_pStatus->GetID(), ulCount); pCtxt->Release(); } // Schedule a callback if (m_pScheduler) { if (!m_pCallback->m_bCallbackPending) { m_pCallback->m_bCallbackPending = TRUE; m_pCallback->m_ulPendingCallbackID = m_pScheduler->RelativeEnter(m_pCallback, 0); } //set the count so that the callback will know how much to read. HX_ASSERT(!m_ulPendingReadCount); // XXXSEH: I suspect ulCount should be added to m_ulPendingReadCount. m_ulPendingReadCount = ulCount; return HXR_OK; } // No scheduler! return HXR_FAIL; } } if (m_bInReadDone) { m_uRecursionCount++; } if (m_uRecursionCount > CMemoryFileSystem::z_uMaxRecursionLevel) { //if there already is a callback registered if(m_pCallback->m_bCallbackPending) { //see if seek canceled him. If he did, //the file sys called Seek while a Read was //pending, so all is good with the callback. if(m_bReadCancelled) { //seek canceled him, so we will make him valid //and use him. m_pCallback->m_bIgnoreCallback = FALSE; m_bReadCancelled = FALSE; //" so IgnoreCallback = FALSE\n"); } else { //the fileformat has called us twice and is bad. return HXR_UNEXPECTED; } } else { if (m_pScheduler) { if (!m_pCallback->m_bCallbackPending) { //there was no callback on the schedule, so make a new one. m_pCallback->m_bIgnoreCallback = FALSE; m_bReadCancelled = FALSE; m_pCallback->m_bCallbackPending = TRUE; m_pCallback->m_ulPendingCallbackID = m_pScheduler->RelativeEnter(m_pCallback, 0); } } else { // no scheduler! return HXR_FAIL; } } //set the count so that the callback will know how much to read. HX_ASSERT(!m_ulPendingReadCount); // XXXSEH: I suspect ulCount should be added to m_ulPendingReadCount. m_ulPendingReadCount = ulCount; return HXR_OK; } // Create buffer object here, notice that we call the // CreateInstance method of the controller, but we could // have implemented our own object that exposed the IHXBuffer // interface. IHXBuffer* pBuffer; HX_RESULT result; if (!m_pCommonClassFactory) { result = m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void **)&m_pCommonClassFactory); if (HXR_OK != result) { return result; } } result = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer); if (HXR_OK != result) { return result; } // Ask the buffer to create a space to read into... result = pBuffer->SetSize(ulCount); if (HXR_OK != result) { return result; } HX_ASSERT(m_pChunkyRes); ULONG32 actual = 0; m_pChunkyRes->GetData(m_ulPos, (char*)pBuffer->GetBuffer(), ulCount, &actual); HX_ASSERT((actual > 0) && (actual <= ulCount)); // Tell the buffer about it's real meaningful size pBuffer->SetSize(actual); m_ulPos += actual; m_bInReadDone = TRUE; // Let the file response sink know about the buffer... result = m_pFileResponse->ReadDone(actual > 0 ? HXR_OK : HXR_FAILED, pBuffer); m_bInReadDone = FALSE; if (m_uRecursionCount > 0) { m_uRecursionCount--; } // Release our reference on the buffer! pBuffer->Release(); return result; } return HXR_UNEXPECTED;}/************************************************************************ * Method: * IHXFileObject::Write * Purpose: * Not allowed to write to a memory file with this interface */STDMETHODIMP CMemoryFileObject::Write(IHXBuffer* pBuffer){ return HXR_UNEXPECTED;}/************************************************************************ * Method: * IHXFileObject::Seek * Purpose: * Seeks to an offset in the file and asynchronously notifies * the caller via the IHXFileResponse interface passed in to Init, * of the completeness of the operation. */STDMETHODIMP CMemoryFileObject::Seek(ULONG32 ulOffset, BOOL bRelative){ if (m_bSeekPending) { m_bSeekPending = FALSE; m_pFileResponse->SeekDone(HXR_CANCELLED); } if(!m_pChunkyRes && m_bCanBeReOpened) { _OpenFile(m_ulFlags); } if (m_pChunkyRes) { /* * Seek cancels pending Reads. */ if(m_pCallback && m_pCallback->m_bCallbackPending && !m_bReadCancelled) { m_pCallback->m_bIgnoreCallback = TRUE; m_bReadCancelled = TRUE; m_pFileResponse->ReadDone(HXR_CANCELLED, NULL); } if(bRelative) { m_ulPos += ulOffset; } else { m_ulPos = ulOffset; } if (m_ulPos < m_pStatus->GetSize()) { return m_pFileResponse->SeekDone(HXR_OK); } else { // XXXNH: until we have pending seek support, respond with an error return m_pFileResponse->SeekDone(HXR_WOULD_BLOCK); } } return HXR_UNEXPECTED;}/************************************************************************ * Method: * IHXFileObject::Stat * Purpose: * Collects information about the file that is returned to the * caller in an IHXStat object */STDMETHODIMP CMemoryFileObject::Stat(IHXFileStatResponse* pFileStatResponse){ HX_ASSERT(m_pStatus); HX_ASSERT(pFileStatResponse); if (m_pStatus) { pFileStatResponse->StatDone(HXR_OK, m_pStatus->GetContentSize(), 0, 0, 0, 0); } else { pFileStatResponse->StatDone(HXR_UNEXPECTED, 0, 0, 0, 0, 0); } return HXR_OK;}/************************************************************************ * Method: * IHXFileObject::Advise * Purpose: * To pass information to the File Object */STDMETHODIMP CMemoryFileObject::Advise(ULONG32 ulInfo){ HX_RESULT pnr = HXR_OK; // If we're done, then we're cached and can allow random access, but // otherwise we need to behave like a linear file system if ( ( !m_pStatus || !m_pStatus->GetDone() ) && ( ulInfo == HX_FILEADVISE_RANDOMACCESS ) ) { pnr = HXR_ADVISE_PREFER_LINEAR; } return pnr;}/************************************************************************ * Method: * IHXFileObject::GetFileObjectFromPool * Purpose: * To get another FileObject from the same pool. */STDMETHODIMP CMemoryFileObject::GetFileObjectFromPool ( IHXGetFileFromSamePoolResponse* response){ HX_RESULT lReturnVal = HXR_FAILED; CMemoryFileObject* pFileObject = 0; CHXString new_path; CHXString strFileName; CHXString strURL; IUnknown* pUnknown = 0; char* pNewPath = 0; char* pSeparator = 0; UpdateFileNameMember(); if(!m_pFilename) { pNewPath = new char[strlen(m_base_path) + 1]; strcpy(pNewPath, m_base_path); /* Flawfinder: ignore */ } else { strURL = m_pFilename; // Make a nice local file name from the URL! strFileName = strURL; pNewPath = new char[strlen(strFileName) + 1]; strcpy(pNewPath, (const char*)strFileName); /* Flawfinder: ignore */ pSeparator = ::strrchr(pNewPath, '/'); if(pSeparator) { /* Separator will be added in seturl */ *pSeparator = 0; } else { // started w/filename. no separator implies no path pNewPath[0] = NULL; } } new_path = pNewPath; if (pNewPath) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -