////////////////////////////////////////////////////////////////////////////////
|
// This source file is part of the ZipArchive library source distribution and
|
// is Copyrighted 2000 - 2011 by Artpol Software - Tadeusz Dracz
|
//
|
// 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.
|
//
|
// For the licensing details refer to the License.txt file.
|
//
|
// Web Site: http://www.artpol-software.com
|
////////////////////////////////////////////////////////////////////////////////
|
|
#include "stdafx.h"
|
|
#if _ZIP_FILE_IMPLEMENTATION == ZIP_ZFI_WIN
|
|
#include "ZipFile.h"
|
#include "ZipException.h"
|
#include "ZipPathComponent.h"
|
#include "BitFlag.h"
|
|
#if _MSC_VER < 1300 && !defined INVALID_SET_FILE_POINTER
|
#define INVALID_SET_FILE_POINTER (DWORD)(-1)
|
#endif
|
|
CZipFile::CZipFile()
|
{
|
m_hFile = INVALID_HANDLE_VALUE;
|
}
|
|
CZipFile::CZipFile(LPCTSTR lpszFileName, UINT openFlags)
|
{
|
m_hFile = INVALID_HANDLE_VALUE;
|
Open(lpszFileName, openFlags, true);
|
}
|
|
void CZipFile::ThrowError() const
|
{
|
CZipException::Throw(CZipException::fileError, m_szFileName);
|
}
|
|
bool CZipFile::Open(LPCTSTR lpszFileName, UINT openFlags, bool bThrow)
|
{
|
if (!IsClosed())
|
Close();
|
|
CZipString fileName = lpszFileName;
|
if (fileName.IsEmpty())
|
{
|
return false;
|
}
|
DWORD access;
|
DWORD temp = openFlags & 3;
|
if (temp == modeWrite)
|
{
|
access = GENERIC_WRITE;
|
}
|
else if (temp == modeReadWrite)
|
{
|
access = GENERIC_READ | GENERIC_WRITE;
|
}
|
else
|
{
|
access = GENERIC_READ;
|
}
|
|
DWORD share;
|
temp = openFlags & 0x70;
|
if (temp == shareDenyWrite)
|
{
|
share = FILE_SHARE_READ;
|
}
|
else if (temp == shareDenyRead)
|
{
|
share = FILE_SHARE_WRITE;
|
}
|
else if (temp == shareDenyNone)
|
{
|
share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
}
|
else
|
{
|
share = 0;
|
}
|
CZipPathComponent::AddPrefix(fileName, false);
|
|
DWORD create;
|
if (openFlags & modeCreate)
|
{
|
if (openFlags & modeNoTruncate)
|
{
|
create = OPEN_ALWAYS;
|
}
|
else
|
{
|
create = CREATE_ALWAYS;
|
}
|
}
|
else
|
{
|
create = OPEN_EXISTING;
|
}
|
|
SECURITY_ATTRIBUTES sa;
|
sa.nLength = sizeof(sa);
|
sa.lpSecurityDescriptor = NULL;
|
sa.bInheritHandle = TRUE;
|
m_hFile = ::CreateFile(fileName, access, share, &sa, create, FILE_ATTRIBUTE_NORMAL, NULL);
|
if (m_hFile == INVALID_HANDLE_VALUE)
|
{
|
if (bThrow)
|
ThrowError();
|
else
|
return false;
|
}
|
|
m_szFileName = lpszFileName;
|
return true;
|
}
|
|
|
ULONGLONG CZipFile::GetLength() const
|
{
|
ASSERT(m_hFile != INVALID_HANDLE_VALUE);
|
ULARGE_INTEGER size;
|
size.LowPart = GetFileSize(m_hFile, &size.HighPart);
|
if (size.LowPart == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR)
|
{
|
ThrowError();
|
}
|
|
return size.QuadPart;
|
}
|
|
|
void CZipFile::SetLength(ULONGLONG uNewLen)
|
{
|
ASSERT(m_hFile != INVALID_HANDLE_VALUE);
|
if (uNewLen > _I64_MAX)
|
{
|
CZipException::Throw(CZipException::tooBigSize);
|
}
|
Seek(uNewLen, FILE_BEGIN);
|
if (::SetEndOfFile(m_hFile) == FALSE)
|
{
|
ThrowError();
|
}
|
}
|
|
ULONGLONG CZipFile::GetPosition() const
|
{
|
ASSERT(m_hFile != INVALID_HANDLE_VALUE);
|
|
// do not call Seek, to keep GetPosition const
|
#if (defined(NTDDI_VERSION) && NTDDI_VERSION >=NTDDI_WIN2K) || (_WIN32_WINNT >= 0x0500 && WINVER >= 0x0500)
|
LARGE_INTEGER li, oli = {0};
|
li.QuadPart = (LONGLONG)0;
|
if (::SetFilePointerEx(m_hFile, li, &oli, FILE_CURRENT) == FALSE)
|
{
|
ThrowError();
|
}
|
return oli.QuadPart;
|
#else
|
LARGE_INTEGER li;
|
li.QuadPart = (LONGLONG)0;
|
li.LowPart = ::SetFilePointer(m_hFile, li.LowPart, &li.HighPart, FILE_CURRENT);
|
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
|
{
|
ThrowError();
|
}
|
return li.QuadPart;
|
#endif
|
}
|
|
ULONGLONG CZipFile::Seek(LONGLONG dOff, int nFrom)
|
{
|
ASSERT(m_hFile != INVALID_HANDLE_VALUE);
|
ASSERT(nFrom == FILE_BEGIN || nFrom == FILE_END || nFrom == FILE_CURRENT);
|
|
#if (defined(NTDDI_VERSION) && NTDDI_VERSION >=NTDDI_WIN2K) || (_WIN32_WINNT >= 0x0500 && WINVER >= 0x0500)
|
|
LARGE_INTEGER li, oli = {0};
|
li.QuadPart = (LONGLONG)dOff;
|
if (::SetFilePointerEx(m_hFile, li, &oli, (DWORD)nFrom) == FALSE)
|
{
|
ThrowError();
|
}
|
return oli.QuadPart;
|
#else
|
LARGE_INTEGER li;
|
li.QuadPart = (LONGLONG)dOff;
|
li.LowPart = ::SetFilePointer(m_hFile, li.LowPart, &li.HighPart, (DWORD)nFrom);
|
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
|
{
|
ThrowError();
|
}
|
return li.QuadPart;
|
#endif
|
}
|
|
void CZipFile::Close()
|
{
|
if (IsClosed())
|
return;
|
bool ok = ::CloseHandle(m_hFile) == TRUE;
|
m_hFile = INVALID_HANDLE_VALUE;
|
m_szFileName.Empty();
|
if (!ok)
|
{
|
ThrowError();
|
}
|
}
|
|
void CZipFile::Flush()
|
{
|
ASSERT(m_hFile != INVALID_HANDLE_VALUE);
|
if (::FlushFileBuffers(m_hFile) == FALSE)
|
{
|
ThrowError();
|
}
|
}
|
|
CZipFile::operator HANDLE()
|
{
|
return m_hFile;
|
}
|
|
|
void CZipFile::Write(const void* lpBuf, UINT nCount)
|
{
|
ASSERT(m_hFile != INVALID_HANDLE_VALUE);
|
if (nCount == 0)
|
{
|
return;
|
}
|
DWORD written = 0;
|
if (::WriteFile(m_hFile, lpBuf, nCount, &written, NULL) == FALSE || written != nCount)
|
{
|
ThrowError();
|
}
|
}
|
|
UINT CZipFile::Read(void *lpBuf, UINT nCount)
|
{
|
ASSERT(m_hFile != INVALID_HANDLE_VALUE);
|
if (nCount == 0)
|
{
|
return 0;
|
}
|
DWORD read = 0;
|
if (::ReadFile(m_hFile, lpBuf, nCount, &read, NULL) == FALSE)
|
{
|
ThrowError();
|
}
|
return (UINT)read;
|
|
}
|
|
#endif
|