⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cfilemap.cpp

📁 研读AxCrypt对加解密的处理方法
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        size_t cbThisChunk = m_cbChunk;
        if (m_cbStreamPos + cbThisChunk > m_cbFileSize) {
            cbThisChunk = (size_t)(m_cbFileSize - m_cbStreamPos);
        }

        void *pView, *pUserView;
        pView = MapUserView(m_hMapping, m_cbStreamPos, cbThisChunk, &pUserView, FILE_MAP_READ);
        CSeg *pSeg = new CSegMap(NULL, cbThisChunk, pUserView, pView, m_cbStreamPos, true);
        m_cbStreamPos += cbThisChunk;
        return pSeg;
    }

    /// \brief Initialize member variables etc.
    CSinkMemFile::CSinkMemFile() {
        m_szFileName = NULL;
        m_hFile = INVALID_HANDLE_VALUE;
        m_hMapping = NULL;
        InitializeCriticalSection(&m_CritSect);
        m_cbOutPos = m_cbInPos = 0;
    }

    /// \brief Additional destruction necessary...
    CSinkMemFile::~CSinkMemFile() {
        delete[] m_szFileName;
        DeleteCriticalSection(&m_CritSect);
    }

    /// \brief Get the handle to the opened file
    /// \return An operating system handle to the open file.
    HANDLE
    CSinkMemFile::GetHandle() {
        return m_hFile;
    }

    /// \brief Set file and chunk size
    /// \param szFileName The name of the file, it is copied and saved here.
    /// \param cbChunk The size of the chunks we provide upon request via OutGetSeg() upstream.
    /// \return A pointer to 'this' CSourceMemFile
    CSinkMemFile *
    CSinkMemFile::Init(const TCHAR *szFileName, size_t cbChunk) {
        m_cbChunk = cbChunk;
        size_t cbLen = lstrlen(szFileName);
        CopyMemory(m_szFileName = new _TCHAR[cbLen+1], szFileName, (cbLen + 1) * sizeof (_TCHAR));
        return this;
    }

    /// \brief Close the file, as well as all mappings, set end of file etc.
    ///
    /// Check for errors with GetErrorCode()
    /// \return true to propagate the close.
    bool
    CSinkMemFile::OutClose() {
        if (m_hMapping) {
            do { // Once, poor mans try
                if (!CloseHandle(m_hMapping)) {
                    SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Close failed to close mapping [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
                    break;
                }
                m_hMapping = NULL;
            } while (false);
        }
        if (m_hFile != INVALID_HANDLE_VALUE) {
            do { // Once
                //
                //  Set end of file pointer, this is determined by m_cbOutPos
                //
                if (SetFilePointer(m_hFile, ((LARGE_INTEGER *)&m_cbOutPos)->LowPart, &((LARGE_INTEGER *)&m_cbOutPos)->HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
                    SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Close set file pointer to end failed [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
                    break;
                }
                if (!SetEndOfFile(m_hFile)) {
                    DWORD dwErr = GetLastError();
                    SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Close can't set end of file [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
                    break;
                }
                if (!CloseHandle(m_hFile)) {
                    SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Close failed to close file [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
                    break;
                }
                m_hFile = INVALID_HANDLE_VALUE;
            } while (false);
        }
        return true;
    }
    /// \brief Get a writeable segment, mapped to the output file if possible.
    ///
    /// Map a request for an output segment directly to the output file. If necessary,
    /// re-create a mapping to a possibly extended file.
    ///
    /// For this to be useful, the upstream caller must get segments in the same
    /// sequence that they are output, and also keep them the same size, i.e. not
    /// get a segment and then change the CSeg::Len() or CSeg::Drop() bytes off it.
    /// In fact using CSeg::Drop() will cause undefined effects. Shortening is
    /// possible, but strongly recommended against, as it will make the code quite
    /// inefficient.
    /// \param cb The size in bytes of the segment to get.
    /// \return A (possibly memory mapped) pointer to a CSeg of the requested size.
    CSeg *
    CSinkMemFile::OutGetSeg(size_t cb) {
        CSeg *pSeg;

        EnterCriticalSection(&m_CritSect);
        // We can only get a mapped segment if we have an open file already.
        longlong cbPos = m_cbInPos > m_cbOutPos ? m_cbInPos : m_cbOutPos;
        if (m_hFile != INVALID_HANDLE_VALUE) {
            if (cbPos + cb > m_cbMappingSize) {
                m_cbMappingSize = cbPos + cb;
                if (m_hMapping) {
                    // This actually works even if we have open views, the order
                    // of calls to unmapview and closehandle is not important.
                    if (!CloseHandle(m_hMapping)) {
                        SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::OutGetSeg failed to close mapping [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
                        LeaveCriticalSection(&m_CritSect);
                        return NULL;
                    }
                    m_hMapping = NULL;
                }
            }
            if (!m_hMapping) {
                // Now create a mapping that is large enough for the largest stream to date.
                m_hMapping = CreateFileMapping(m_hFile, NULL, PAGE_READWRITE, ((LARGE_INTEGER *)&m_cbMappingSize)->HighPart, ((LARGE_INTEGER *)&m_cbMappingSize)->LowPart, NULL);
                if (!m_hMapping) {
                    SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::OutGetSeg failed to create file mapping [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
                    LeaveCriticalSection(&m_CritSect);
                    return NULL;
                }
            }
            void *pView, *pUserView;
            pView = MapUserView(m_hMapping, cbPos, cb, &pUserView, FILE_MAP_WRITE|FILE_MAP_READ);
            pSeg = new CSegMap(this, cb, pUserView, pView, cbPos);
        } else {
            pSeg = new CSeg(cb);
        }
        m_cbInPos = cbPos + cb;
        LeaveCriticalSection(&m_CritSect);
        return pSeg;
    }
    /// \brief Write a segment to the file, optimizing the case where it already is a mapping.
    ///
    /// Write a segment to the file by copying into a memory mapped segment, unless
    /// we're already such a segment, in which case we actually need do nothing except
    /// keep track of the length of valid data 'written'.
    /// \param pSeg The segment, possibly actually a CSegMap, determined by run time type info.
    void
    CSinkMemFile::Out(CSeg *pSeg) {
        if (CSeg::IsSeg(pSeg)) {
            // We need to be in a critical section, since the previous section of
            // the pipe may be in a different thread and may request allocation from
            // OutGetSeg().
            EnterCriticalSection(&m_CritSect);
            if (pSeg->Len()) {
                // If this is not a CSegMap, or if it is, we're not the owner then we allocate an output.
                if ((pSeg->RTClassId() != CSegMap::ClassId()) || !((CSegMap *)pSeg)->IsOwner(this)) {
                    CSeg *pOutSeg = OutGetSeg(pSeg->Len());
                    if (!pOutSeg) {
                        SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Out() [OutGetSeg() returned NULL]"));
                    } else {
                        CopyMemory(pOutSeg->PtrWr(), pSeg->PtrRd(), pSeg->Len());
                        pOutSeg->Release();
                    }
                } else {
                    // If we're 'short' of data in the output, we move the segment
                    // back. This can happen if an earlier requested segment was cut
                    // short before being output.
                    CSegMap *pSegMap = (CSegMap *)pSeg;
                    if (pSegMap->GetPos() > m_cbOutPos) {
                        void *pView, *pUserView;
                        pView = MapUserView(m_hMapping, m_cbOutPos, pSegMap->Len(), &pUserView, FILE_MAP_WRITE|FILE_MAP_READ);
                        if (!pView) {
                            SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Out() [MapUserView() returned NULL]"));
                        } else {
                            CopyMemory(pUserView, pSegMap->PtrRd(), pSegMap->Len());
                            if (!(UnmapViewOfFile(pView))) {
                                SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Out() [UnmapViewOfFile() failed: %s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
                            }
                        }
                    } else if (pSegMap->GetPos() < m_cbOutPos) {
                        // If we've already output into this segment, it's run over and
                        // we've violated the stream model. This can happen if a non-mapped
                        // segment is gotten, and then before it's 'output', a non-mapped
                        // segment is output. This is an error condition.
                        SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::Out() [Output sequence error]"));
                    }
                    // If (which is the normal case) the output-position is the same as the
                    // segment's start, everything is ok and we do nothing.
                }
            }
            m_cbOutPos += pSeg->Len();
            pSeg->Release();
            LeaveCriticalSection(&m_CritSect);
        }
    }
    /// \brief Open the file named in Init() for output
    ///
    /// Check for errors with GetErrorCode().
    /// \return true to propagate the open, which we do if no error. false is not an error condition.
    bool
    CSinkMemFile::OutOpen() {
        // If it's there, open for writing, otherwise create it.
        m_hFile = CreateFile(m_szFileName, GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
        if (m_hFile == INVALID_HANDLE_VALUE) {
            SetError(ERROR_CODE_GENERIC, _T("CSinkMemFile::CSinkMemFile open error [%s]"), my_ptr<_TCHAR>(AxLib::APerror(m_szFileName)).get());
        }
        ((LARGE_INTEGER *)&m_cbMappingSize)->LowPart = GetFileSize(m_hFile, (LPDWORD)&(((LARGE_INTEGER *)&m_cbMappingSize)->HighPart));
        m_cbOutPos = m_cbInPos = 0;
        return true;
    }
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -