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

📄 cfileio.cpp

📁 研读AxCrypt对加解密的处理方法
💻 CPP
字号:
/*! \file
    \brief Implementation of AxPipe::CSourceFileIO and AxPipe::CSinkFileIO, Win32 File IO

    @(#) $Id$

    AxPipe - Binary Stream Framework

    Copyright (C) 2003 Svante Seleborg/Axon Data, All rights reserved.

    This program is free software; you can redistribute it and/or modify it under the terms
    of the GNU General Public License as published by the Free Software Foundation;
    either version 2 of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
    without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along with this program;
    if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
    Boston, MA 02111-1307 USA

    The author may be reached at mailto:axpipe@axondata.se and http://axpipe.sourceforge.net

    Why is this framework released as GPL and not LGPL? See http://www.gnu.org/philosophy/why-not-lgpl.html

----
\verbatim
    CFileIO.cpp                     Implementation of CSourceFileIO and CSinkFileIO, Win32 files

    E-mail                          YYYY-MM-DD              Reason
    axpipe@axondata.se              2005-05-18              Initial
\endverbatim
*/
#include "stdafx.h"
#include "CFileIO.h"

#include "AxAssert.h"
#define AXLIB_ASSERT_FILE "CFileIO.cpp"

namespace AxPipe {
    /// \brief Just initialize member variables
    CSourceFileIO::CSourceFileIO() {
        m_szFileName = NULL;
        m_hFile = INVALID_HANDLE_VALUE;
    }

    /// \brief Additional destruction necessary...
    CSourceFileIO::~CSourceFileIO() {
        delete[] m_szFileName;
    }

    /// \brief Get the file path used
    /// \return A pointer to the path used. Owned by this class. Deleted here.
    const _TCHAR *
    CSourceFileIO::GetFilePath() {
        return m_szFileName;
    }

    /// \brief Get the handle to the opened file
    /// \return An operating system handle to the open file.
    HANDLE
    CSourceFileIO::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 send downstream
    /// \return A pointer to 'this' CSourceFileIO
    CSourceFileIO *CSourceFileIO::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 Use an open sink as the source instead. Must be used in/before OutClose() of the sink
    /// \param pSink Pointer to a CSinkFileIO, must be open.
    /// \param cbChunk The size of the chunks we send downstream
    /// \return A pointer to 'this' CSourceFileIO
    CSourceFileIO *CSourceFileIO::Init(CSinkFileIO *pSink, size_t cbChunk) {
        // Use a duplicate of the handle, so we can close it normally
        if (DuplicateHandle(GetCurrentProcess(), pSink->m_hFile, GetCurrentProcess(), &m_hFile, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) {
            SetError(ERROR_CODE_GENERIC, _T("CSourceFileIO::CSourceFileIO DuplicateHandle error [%s]"), my_ptr<_TCHAR>(AxLib::APerror(pSink->m_szFileName)).get());
            return this;
        }
        return Init(pSink->m_szFileName, cbChunk);
    }

    /// \brief Open the file
    ///
    /// The filename is provided in the Init() call.
    /// Check for error with GetErrorCode().
    /// \return true if we are to propagate, which we do if no error occurred. false is not an error indication though.
    bool CSourceFileIO::OutOpen() {
        if (m_hFile == INVALID_HANDLE_VALUE) {
            m_hFile = CreateFile(m_szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
            if (m_hFile == INVALID_HANDLE_VALUE) {
                SetError(ERROR_CODE_GENERIC, _T("CSourceFileIO::CSourceFileIO open error [%s]"), my_ptr<_TCHAR>(AxLib::APerror(m_szFileName)).get());
                return false;                   // No point propagating if we already failed
            }
        }
        // Find out how large the file is
        LARGE_INTEGER li;
        if (GetFileSizeEx(m_hFile, &li) == 0) {
            SetError(ERROR_CODE_GENERIC, _T("CSourceFileIO::CSourceFileIO GetFileSizeEx error [%s]"), my_ptr<_TCHAR>(AxLib::APerror(m_szFileName)).get());
            return false;                   // No point propagating if we already failed
        }
        m_cbFileSize = li.QuadPart;
        // Get the current location in the file - normally zero, but just to be careful since we may be re-using an open handle
        li.QuadPart = 0;
        if (SetFilePointerEx(m_hFile, li, reinterpret_cast<PLARGE_INTEGER>(&m_cbStreamPos), FILE_CURRENT) == 0) {
            SetError(ERROR_CODE_GENERIC, _T("CSourceFileIO::CSourceFileIO SetFilePointerEx error [%s]"), my_ptr<_TCHAR>(AxLib::APerror(m_szFileName)).get());
            return false;                   // No point propagating if we already failed
        }
        return true;
    }

    /// \brief Close the file
    ///
    /// Check for error with GetErrorCode().
    /// \return true if propagation of the close is recommended, which it is if no error. false is not error indication though.
    bool CSourceFileIO::OutClose(void) {
        if (m_hFile != INVALID_HANDLE_VALUE) {
            if (!CloseHandle(m_hFile)) {
                SetError(ERROR_CODE_GENERIC, _T("CSourceFileIO::Close failed to close file [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
                return true;
            }
            m_hFile = INVALID_HANDLE_VALUE;
        }
        return true;
    }

    /// \brief Get the next chunk from the input file
    ///
    /// Multiple calls on EOF conditions are allowed.
    ///
    /// \return A chunk, or zero-length on End-Of-File, or NULL on error.
    CSeg *CSourceFileIO::In() {
        if (m_cbStreamPos == m_cbFileSize) {
            return new CSeg;    // Return a zero-sized segment.
        }
        size_t cbThisChunk = m_cbChunk;
        if (m_cbStreamPos + cbThisChunk > m_cbFileSize) {
            cbThisChunk = (size_t)(m_cbFileSize - m_cbStreamPos);
        }
		DWORD cbBytesRead = 0;
		CSeg *pSeg = new CSeg(cbThisChunk);
		ASSPTR(pSeg);

		if (!ReadFile(m_hFile, pSeg->PtrWr(), (DWORD)cbThisChunk, &cbBytesRead, FALSE)) {
            SetError(ERROR_CODE_GENERIC, _T("CSourceFileIO::In() failed to read file [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
		}

        m_cbStreamPos += cbBytesRead;
        return pSeg;
    }

    /// \brief Initialize member variables etc.
    CSinkFileIO::CSinkFileIO() {
        m_szFileName = NULL;
        m_hFile = INVALID_HANDLE_VALUE;
        m_cbOutPos = 0;
    }

    /// \brief Additional destruction necessary...
    CSinkFileIO::~CSinkFileIO() {
        delete[] m_szFileName;
    }

    /// \brief Get the file path used
    /// \return A pointer to the path used. Owned by this class. Deleted here.
    const _TCHAR *
    CSinkFileIO::GetFilePath() {
        return m_szFileName;
    }

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

    /// \brief Set the file pointer. Do not truncate.
    void
    CSinkFileIO::SetFilePos(longlong i) {
        LARGE_INTEGER li;
        li.QuadPart = i;
        if (!::SetFilePointerEx(m_hFile, li, NULL, FILE_BEGIN)) {
            SetError(ERROR_CODE_GENERIC, _T("CSinkFileIO::SetFilePointerEx failed [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
        }
        m_cbOutPos = i;
    }

    /// \brief Set the end-of-file pointer at the current position.
    void
    CSinkFileIO::SetFileEnd() {
        if (!::SetEndOfFile(m_hFile)) {
            SetError(ERROR_CODE_GENERIC, _T("CSinkFileIO::Can't set end of file [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
        }
    }

    /// \brief Get the current size of the file.
    longlong
    CSinkFileIO::FileSize() {
        LARGE_INTEGER li;
        if (!::GetFileSizeEx(m_hFile, &li)) {
            SetError(ERROR_CODE_GENERIC, _T("CSinkFileIO::Can't get size of file [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
        }
        return static_cast<longlong>(li.QuadPart);
    }

    /// \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' CSinkFileIO
    CSinkFileIO *
    CSinkFileIO::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
    CSinkFileIO::OutClose() {
        if (m_hFile != INVALID_HANDLE_VALUE) {
            do { // Once
                //
                //  Set end of file pointer
                //
                if (!::SetEndOfFile(m_hFile)) {
                    DWORD dwErr = GetLastError();
                    SetError(ERROR_CODE_GENERIC, _T("CSinkFileIO::Close can't set end of file [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
                    break;
                }
                if (!::CloseHandle(m_hFile)) {
                    SetError(ERROR_CODE_GENERIC, _T("CSinkFileIO::Close failed to close file [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
                    break;
                }
                m_hFile = INVALID_HANDLE_VALUE;
            } while (false);
        }
        return true;
    }

	/// \brief Write a segment to the file
    /// \param pSeg The segment
    void
    CSinkFileIO::Out(CSeg *pSeg) {
		DWORD cbBytesWritten;
        if (!::WriteFile(m_hFile, pSeg->PtrRd(), (DWORD)pSeg->Len(), &cbBytesWritten, FALSE)) {
            SetError(ERROR_CODE_GENERIC, _T("CSinkFileIO::Out() failed to write file [%s]"), my_ptr<_TCHAR>(AxLib::APerror()).get());
		}
		m_cbOutPos += pSeg->Len();
        pSeg->Release();
    }

    /// \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
    CSinkFileIO::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("CSinkFileIO::CSinkFileIO open error [%s]"), my_ptr<_TCHAR>(AxLib::APerror(m_szFileName)).get());
        }
        m_cbOutPos = 0;
        return true;
    }
};

⌨️ 快捷键说明

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