mirror of
https://github.com/Xevion/easy7zip.git
synced 2026-02-01 00:24:14 -06:00
9.34
This commit is contained in:
committed by
Kornel Lesiński
parent
83f8ddcc5b
commit
f08f4dcc3c
Executable → Regular
+170
-123
@@ -2,88 +2,35 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
#include "../../C/Alloc.h"
|
||||
#endif
|
||||
|
||||
#include "FileIO.h"
|
||||
#include "FileName.h"
|
||||
|
||||
#ifndef _UNICODE
|
||||
extern bool g_IsNT;
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NName;
|
||||
|
||||
namespace NWindows {
|
||||
namespace NFile {
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
|
||||
bool IsDeviceName(CFSTR n)
|
||||
namespace NSystem
|
||||
{
|
||||
#ifdef UNDER_CE
|
||||
int len = (int)MyStringLen(n);
|
||||
if (len < 5 || len > 5 || memcmp(n, FTEXT("DSK"), 3 * sizeof(FCHAR)) != 0)
|
||||
return false;
|
||||
if (n[4] != ':')
|
||||
return false;
|
||||
// for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ));
|
||||
#else
|
||||
if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' || n[3] != '\\')
|
||||
return false;
|
||||
int len = (int)MyStringLen(n);
|
||||
if (len == 6 && n[5] == ':')
|
||||
return true;
|
||||
if (len < 18 || len > 22 || memcmp(n + 4, FTEXT("PhysicalDrive"), 13 * sizeof(FCHAR)) != 0)
|
||||
return false;
|
||||
for (int i = 17; i < len; i++)
|
||||
if (n[i] < '0' || n[i] > '9')
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(WIN_LONG_PATH) && defined(_UNICODE)
|
||||
#define WIN_LONG_PATH2
|
||||
#endif
|
||||
|
||||
#ifdef WIN_LONG_PATH
|
||||
bool GetLongPathBase(CFSTR s, UString &res)
|
||||
{
|
||||
res.Empty();
|
||||
int len = MyStringLen(s);
|
||||
FChar c = s[0];
|
||||
if (len < 1 || c == '\\' || c == '.' && (len == 1 || len == 2 && s[1] == '.'))
|
||||
return true;
|
||||
UString curDir;
|
||||
bool isAbs = false;
|
||||
if (len > 3)
|
||||
isAbs = (s[1] == ':' && s[2] == '\\' && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'));
|
||||
|
||||
if (!isAbs)
|
||||
{
|
||||
WCHAR temp[MAX_PATH + 2];
|
||||
temp[0] = 0;
|
||||
DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, temp);
|
||||
if (needLength == 0 || needLength > MAX_PATH)
|
||||
return false;
|
||||
curDir = temp;
|
||||
if (curDir.Back() != L'\\')
|
||||
curDir += L'\\';
|
||||
}
|
||||
res = UString(L"\\\\?\\") + curDir + fs2us(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetLongPath(CFSTR path, UString &longPath)
|
||||
{
|
||||
if (GetLongPathBase(path, longPath))
|
||||
return !longPath.IsEmpty();
|
||||
return false;
|
||||
bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace NIO {
|
||||
|
||||
CFileBase::~CFileBase() { Close(); }
|
||||
|
||||
bool CFileBase::Create(CFSTR fileName, DWORD desiredAccess,
|
||||
bool CFileBase::Create(CFSTR path, DWORD desiredAccess,
|
||||
DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
|
||||
{
|
||||
if (!Close())
|
||||
@@ -96,19 +43,20 @@ bool CFileBase::Create(CFSTR fileName, DWORD desiredAccess,
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
_handle = ::CreateFile(fs2fas(fileName), desiredAccess, shareMode,
|
||||
_handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode,
|
||||
(LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_handle = ::CreateFileW(fs2us(fileName), desiredAccess, shareMode,
|
||||
IF_USE_MAIN_PATH
|
||||
_handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode,
|
||||
(LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (_handle == INVALID_HANDLE_VALUE)
|
||||
if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetLongPath(fileName, longPath))
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
_handle = ::CreateFileW(longPath, desiredAccess, shareMode,
|
||||
(LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);
|
||||
}
|
||||
@@ -135,9 +83,9 @@ bool CFileBase::GetPosition(UInt64 &position) const
|
||||
bool CFileBase::GetLength(UInt64 &length) const
|
||||
{
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
if (IsDeviceFile && LengthDefined)
|
||||
if (IsDeviceFile && SizeDefined)
|
||||
{
|
||||
length = Length;
|
||||
length = Size;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -154,95 +102,192 @@ bool CFileBase::GetLength(UInt64 &length) const
|
||||
bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const
|
||||
{
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
if (IsDeviceFile && LengthDefined && moveMethod == FILE_END)
|
||||
if (IsDeviceFile && SizeDefined && moveMethod == FILE_END)
|
||||
{
|
||||
distanceToMove += Length;
|
||||
distanceToMove += Size;
|
||||
moveMethod = FILE_BEGIN;
|
||||
}
|
||||
#endif
|
||||
|
||||
LARGE_INTEGER value;
|
||||
value.QuadPart = distanceToMove;
|
||||
value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod);
|
||||
if (value.LowPart == 0xFFFFFFFF)
|
||||
LONG high = (LONG)(distanceToMove >> 32);
|
||||
DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod);
|
||||
if (low == 0xFFFFFFFF)
|
||||
if (::GetLastError() != NO_ERROR)
|
||||
return false;
|
||||
newPosition = value.QuadPart;
|
||||
newPosition = (((UInt64)high) << 32) + low;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFileBase::Seek(UInt64 position, UInt64 &newPosition)
|
||||
bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const
|
||||
{
|
||||
return Seek(position, FILE_BEGIN, newPosition);
|
||||
}
|
||||
|
||||
bool CFileBase::SeekToBegin()
|
||||
bool CFileBase::SeekToBegin() const
|
||||
{
|
||||
UInt64 newPosition;
|
||||
return Seek(0, newPosition);
|
||||
}
|
||||
|
||||
bool CFileBase::SeekToEnd(UInt64 &newPosition)
|
||||
bool CFileBase::SeekToEnd(UInt64 &newPosition) const
|
||||
{
|
||||
return Seek(0, FILE_END, newPosition);
|
||||
}
|
||||
|
||||
/*
|
||||
bool CFileBase::GetFileInformation(CByHandleFileInfo &fi) const
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION wfi;
|
||||
if (!::GetFileInformationByHandle(_handle, &wfi))
|
||||
return false;
|
||||
fi.Attrib = wfi.dwFileAttributes;
|
||||
fi.CTime = wfi.ftCreationTime;
|
||||
fi.ATime = wfi.ftLastAccessTime;
|
||||
fi.MTime = wfi.ftLastWriteTime;
|
||||
fi.Size = (((UInt64)wfi.nFileSizeHigh) << 32) + wfi.nFileSizeLow;
|
||||
fi.VolumeSerialNumber = wfi.dwVolumeSerialNumber;
|
||||
fi.NumLinks = wfi.nNumberOfLinks;
|
||||
fi.FileIndex = (((UInt64)wfi.nFileIndexHigh) << 32) + wfi.nFileIndexLow;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
/////////////////////////
|
||||
// CInFile
|
||||
// ---------- CInFile ---------
|
||||
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
void CInFile::GetDeviceLength()
|
||||
|
||||
void CInFile::CorrectDeviceSize()
|
||||
{
|
||||
if (_handle != INVALID_HANDLE_VALUE && IsDeviceFile)
|
||||
// maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail
|
||||
static const UInt32 kClusterSize = 1 << 14;
|
||||
UInt64 pos = Size & ~(UInt64)(kClusterSize - 1);
|
||||
UInt64 realNewPosition;
|
||||
if (!Seek(pos, realNewPosition))
|
||||
return;
|
||||
Byte *buf = (Byte *)MidAlloc(kClusterSize);
|
||||
|
||||
bool needbackward = true;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
#ifdef UNDER_CE
|
||||
LengthDefined = true;
|
||||
Length = 128 << 20;
|
||||
UInt32 processed = 0;
|
||||
// up test is slow for "PhysicalDrive".
|
||||
// processed size for latest block for "PhysicalDrive0" is 0.
|
||||
if (!Read1(buf, kClusterSize, processed))
|
||||
break;
|
||||
if (processed == 0)
|
||||
break;
|
||||
needbackward = false;
|
||||
Size = pos + processed;
|
||||
if (processed != kClusterSize)
|
||||
break;
|
||||
pos += kClusterSize;
|
||||
}
|
||||
|
||||
#else
|
||||
PARTITION_INFORMATION partInfo;
|
||||
LengthDefined = true;
|
||||
Length = 0;
|
||||
if (needbackward && pos != 0)
|
||||
{
|
||||
pos -= kClusterSize;
|
||||
for (;;)
|
||||
{
|
||||
// break;
|
||||
if (!Seek(pos, realNewPosition))
|
||||
break;
|
||||
if (!buf)
|
||||
{
|
||||
buf = (Byte *)MidAlloc(kClusterSize);
|
||||
if (!buf)
|
||||
break;
|
||||
}
|
||||
UInt32 processed = 0;
|
||||
// that code doesn't work for "PhysicalDrive0"
|
||||
if (!Read1(buf, kClusterSize, processed))
|
||||
break;
|
||||
if (processed != 0)
|
||||
{
|
||||
Size = pos + processed;
|
||||
break;
|
||||
}
|
||||
if (pos == 0)
|
||||
break;
|
||||
pos -= kClusterSize;
|
||||
}
|
||||
}
|
||||
MidFree(buf);
|
||||
}
|
||||
|
||||
if (GetPartitionInfo(&partInfo))
|
||||
Length = partInfo.PartitionLength.QuadPart;
|
||||
|
||||
void CInFile::CalcDeviceSize(CFSTR s)
|
||||
{
|
||||
SizeDefined = false;
|
||||
Size = 0;
|
||||
if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile)
|
||||
return;
|
||||
#ifdef UNDER_CE
|
||||
|
||||
SizeDefined = true;
|
||||
Size = 128 << 20;
|
||||
|
||||
#else
|
||||
|
||||
PARTITION_INFORMATION partInfo;
|
||||
bool needCorrectSize = true;
|
||||
|
||||
/*
|
||||
WinXP 64-bit:
|
||||
|
||||
HDD \\.\PhysicalDrive0 (MBR):
|
||||
GetPartitionInfo == GeometryEx : corrrect size? (includes tail)
|
||||
Geometry : smaller than GeometryEx (no tail, maybe correct too?)
|
||||
MyGetDiskFreeSpace : FAIL
|
||||
Size correction is slow and block size (kClusterSize) must be small?
|
||||
|
||||
HDD partition \\.\N: (NTFS):
|
||||
MyGetDiskFreeSpace : Size of NTFS clusters. Same size can be calculated after correction
|
||||
GetPartitionInfo : size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS
|
||||
Geometry / CdRomGeometry / GeometryEx : size of HDD (not that partition)
|
||||
|
||||
CD-ROM drive (ISO):
|
||||
MyGetDiskFreeSpace : correct size. Same size can be calculated after correction
|
||||
Geometry == CdRomGeometry : smaller than corrrect size
|
||||
GetPartitionInfo == GeometryEx : larger than corrrect size
|
||||
|
||||
Floppy \\.\a: (FAT):
|
||||
Geometry : correct size.
|
||||
CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL
|
||||
correction works OK for FAT.
|
||||
correction works OK for non-FAT, if kClusterSize = 512.
|
||||
*/
|
||||
|
||||
if (GetPartitionInfo(&partInfo))
|
||||
{
|
||||
Size = partInfo.PartitionLength.QuadPart;
|
||||
SizeDefined = true;
|
||||
needCorrectSize = false;
|
||||
if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0)
|
||||
{
|
||||
FChar path[4] = { s[4], ':', '\\', 0 };
|
||||
UInt64 clusterSize, totalSize, freeSize;
|
||||
if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize))
|
||||
Size = totalSize;
|
||||
else
|
||||
needCorrectSize = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SizeDefined)
|
||||
{
|
||||
my_DISK_GEOMETRY_EX geomEx;
|
||||
SizeDefined = GetGeometryEx(&geomEx);
|
||||
if (SizeDefined)
|
||||
Size = geomEx.DiskSize.QuadPart;
|
||||
else
|
||||
{
|
||||
DISK_GEOMETRY geom;
|
||||
if (!GetGeometry(&geom))
|
||||
if (!GetCdRomGeometry(&geom))
|
||||
LengthDefined = false;
|
||||
if (LengthDefined)
|
||||
Length = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;
|
||||
SizeDefined = GetGeometry(&geom);
|
||||
if (!SizeDefined)
|
||||
SizeDefined = GetCdRomGeometry(&geom);
|
||||
if (SizeDefined)
|
||||
Size = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;
|
||||
}
|
||||
// SeekToBegin();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (needCorrectSize && SizeDefined && Size != 0)
|
||||
{
|
||||
CorrectDeviceSize();
|
||||
SeekToBegin();
|
||||
}
|
||||
|
||||
// SeekToBegin();
|
||||
#endif
|
||||
}
|
||||
|
||||
// ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 &&
|
||||
|
||||
#define MY_DEVICE_EXTRA_CODE \
|
||||
IsDeviceFile = IsDeviceName(fileName); \
|
||||
GetDeviceLength();
|
||||
IsDeviceFile = IsDevicePath(fileName); \
|
||||
CalcDeviceSize(fileName);
|
||||
#else
|
||||
#define MY_DEVICE_EXTRA_CODE
|
||||
#endif
|
||||
@@ -305,8 +350,7 @@ bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize)
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// COutFile
|
||||
// ---------- COutFile ---------
|
||||
|
||||
static inline DWORD GetCreationDisposition(bool createAlways)
|
||||
{ return createAlways? CREATE_ALWAYS: CREATE_NEW; }
|
||||
@@ -320,6 +364,9 @@ bool COutFile::Open(CFSTR fileName, DWORD creationDisposition)
|
||||
bool COutFile::Create(CFSTR fileName, bool createAlways)
|
||||
{ return Open(fileName, GetCreationDisposition(createAlways)); }
|
||||
|
||||
bool COutFile::CreateAlways(CFSTR fileName, DWORD flagsAndAttributes)
|
||||
{ return Open(fileName, FILE_SHARE_READ, GetCreationDisposition(true), flagsAndAttributes); }
|
||||
|
||||
bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
|
||||
{ return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user