mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 11:14:58 -06:00
9.04 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
8874e4fbc9
commit
829409452d
@@ -2,48 +2,118 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "resource.h"
|
||||
#include "../../../../C/Alloc.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/StringConvert.h"
|
||||
|
||||
#include "Windows/Defs.h"
|
||||
#include "Windows/FileDir.h"
|
||||
#include "Windows/FileIO.h"
|
||||
#include "Windows/FileSystem.h"
|
||||
#include "Windows/PropVariant.h"
|
||||
|
||||
#include "../../PropID.h"
|
||||
|
||||
#include "FSDrives.h"
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/ComTry.h"
|
||||
#include "../../PropID.h"
|
||||
#include "Windows/Defs.h"
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/FileDir.h"
|
||||
#include "Windows/FileSystem.h"
|
||||
|
||||
#include "SysIconUtils.h"
|
||||
#include "FSFolder.h"
|
||||
#include "PhysDriveFolder.h"
|
||||
#include "LangUtils.h"
|
||||
#include "SysIconUtils.h"
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NFind;
|
||||
|
||||
static const STATPROPSTG kProperties[] =
|
||||
static const wchar_t *kVolPrefix = L"\\\\.\\";
|
||||
|
||||
UString CDriveInfo::GetDeviceFileIoName() const
|
||||
{
|
||||
{ NULL, kpidName, VT_BSTR},
|
||||
// { NULL, kpidIsDir, VT_BOOL},
|
||||
{ L"Total Size", kpidTotalSize, VT_UI8},
|
||||
{ L"Free Space", kpidFreeSpace, VT_UI8},
|
||||
{ NULL, kpidType, VT_BSTR},
|
||||
{ L"Label", kpidVolumeName, VT_BSTR},
|
||||
{ L"File system", kpidFileSystem, VT_BSTR},
|
||||
{ L"Cluster Size", kpidClusterSize, VT_UI8}
|
||||
return kVolPrefix + Name;
|
||||
}
|
||||
|
||||
struct CPhysTempBuffer
|
||||
{
|
||||
void *buffer;
|
||||
CPhysTempBuffer(): buffer(0) {}
|
||||
~CPhysTempBuffer() { MidFree(buffer); }
|
||||
};
|
||||
|
||||
static const wchar_t *kDriveTypes[] =
|
||||
static HRESULT CopyFileSpec(LPCWSTR fromPath, LPCWSTR toPath, bool writeToDisk, UInt64 fileSize,
|
||||
UInt32 bufferSize, UInt64 progressStart, IProgress *progress)
|
||||
{
|
||||
L"Unknown",
|
||||
L"No Root Dir",
|
||||
L"Removable",
|
||||
L"Fixed",
|
||||
L"Remote",
|
||||
L"CD-ROM",
|
||||
L"RAM disk"
|
||||
NFile::NIO::CInFile inFile;
|
||||
if (!inFile.Open(fromPath))
|
||||
return GetLastError();
|
||||
if (fileSize == (UInt64)(Int64)-1)
|
||||
{
|
||||
if (!inFile.GetLength(fileSize))
|
||||
::GetLastError();
|
||||
}
|
||||
NFile::NIO::COutFile outFile;
|
||||
if (writeToDisk)
|
||||
{
|
||||
if (!outFile.Open(toPath, FILE_SHARE_WRITE, OPEN_EXISTING, 0))
|
||||
return GetLastError();
|
||||
}
|
||||
else
|
||||
if (!outFile.Create(toPath, true))
|
||||
return GetLastError();
|
||||
CPhysTempBuffer tempBuffer;
|
||||
tempBuffer.buffer = MidAlloc(bufferSize);
|
||||
if (tempBuffer.buffer == 0)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
for (UInt64 pos = 0; pos < fileSize;)
|
||||
{
|
||||
UInt64 progressCur = progressStart + pos;
|
||||
RINOK(progress->SetCompleted(&progressCur));
|
||||
UInt64 rem = fileSize - pos;
|
||||
UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize);
|
||||
UInt32 processedSize;
|
||||
if (!inFile.Read(tempBuffer.buffer, curSize, processedSize))
|
||||
return GetLastError();
|
||||
if (processedSize == 0)
|
||||
break;
|
||||
curSize = processedSize;
|
||||
if (writeToDisk)
|
||||
{
|
||||
const UInt32 kMask = 0x1FF;
|
||||
curSize = (curSize + kMask) & ~kMask;
|
||||
if (curSize > bufferSize)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (!outFile.Write(tempBuffer.buffer, curSize, processedSize))
|
||||
return GetLastError();
|
||||
if (curSize != processedSize)
|
||||
return E_FAIL;
|
||||
pos += curSize;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidName, VT_BSTR},
|
||||
{ NULL, kpidTotalSize, VT_UI8},
|
||||
{ NULL, kpidFreeSpace, VT_UI8},
|
||||
{ NULL, kpidType, VT_BSTR},
|
||||
{ NULL, kpidVolumeName, VT_BSTR},
|
||||
{ NULL, kpidFileSystem, VT_BSTR},
|
||||
{ NULL, kpidClusterSize, VT_UI8}
|
||||
};
|
||||
|
||||
static const char *kDriveTypes[] =
|
||||
{
|
||||
"Unknown",
|
||||
"No Root Dir",
|
||||
"Removable",
|
||||
"Fixed",
|
||||
"Remote",
|
||||
"CD-ROM",
|
||||
"RAM disk"
|
||||
};
|
||||
|
||||
STDMETHODIMP CFSDrives::LoadItems()
|
||||
@@ -60,18 +130,13 @@ STDMETHODIMP CFSDrives::LoadItems()
|
||||
|
||||
di.FullSystemName = driveName;
|
||||
|
||||
di.Name = di.FullSystemName.Left(
|
||||
di.FullSystemName.Length() - 1);
|
||||
di.Name = di.FullSystemName.Left(di.FullSystemName.Length() - 1);
|
||||
di.ClusterSize = 0;
|
||||
di.DriveSize = 0;
|
||||
di.FreeSpace = 0;
|
||||
UINT driveType = NFile::NSystem::MyGetDriveType(driveName);
|
||||
if (driveType < sizeof(kDriveTypes) / sizeof(kDriveTypes[0]))
|
||||
{
|
||||
di.Type = kDriveTypes[driveType];
|
||||
}
|
||||
di.DriveType = NFile::NSystem::MyGetDriveType(driveName);
|
||||
bool needRead = true;
|
||||
if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE)
|
||||
if (di.DriveType == DRIVE_CDROM || di.DriveType == DRIVE_REMOVABLE)
|
||||
{
|
||||
/*
|
||||
DWORD dwSerialNumber;`
|
||||
@@ -117,12 +182,15 @@ STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT
|
||||
const CDriveInfo &di = _drives[itemIndex];
|
||||
switch(propID)
|
||||
{
|
||||
case kpidIsDir: prop = true; break;
|
||||
case kpidIsDir: prop = !_volumeMode; break;
|
||||
case kpidName: prop = di.Name; break;
|
||||
case kpidTotalSize: if (di.KnownSizes) prop = di.DriveSize; break;
|
||||
case kpidFreeSpace: if (di.KnownSizes) prop = di.FreeSpace; break;
|
||||
case kpidClusterSize: if (di.KnownSizes) prop = di.ClusterSize; break;
|
||||
case kpidType: prop = di.Type; break;
|
||||
case kpidType:
|
||||
if (di.DriveType < sizeof(kDriveTypes) / sizeof(kDriveTypes[0]))
|
||||
prop = kDriveTypes[di.DriveType];
|
||||
break;
|
||||
case kpidVolumeName: prop = di.VolumeName; break;
|
||||
case kpidFileSystem: prop = di.FileSystemName; break;
|
||||
}
|
||||
@@ -133,6 +201,8 @@ STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT
|
||||
HRESULT CFSDrives::BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder)
|
||||
{
|
||||
*resultFolder = 0;
|
||||
if (_volumeMode)
|
||||
return S_OK;
|
||||
NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
|
||||
CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;
|
||||
RINOK(fsFolderSpec->Init(name, 0));
|
||||
@@ -146,6 +216,7 @@ STDMETHODIMP CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
|
||||
if (index >= (UInt32)_drives.Size())
|
||||
return E_INVALIDARG;
|
||||
const CDriveInfo &di = _drives[index];
|
||||
/*
|
||||
if (_volumeMode)
|
||||
{
|
||||
*resultFolder = 0;
|
||||
@@ -155,6 +226,7 @@ STDMETHODIMP CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
|
||||
*resultFolder = subFolder.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
return BindToFolderSpec(di.FullSystemName, resultFolder);
|
||||
}
|
||||
|
||||
@@ -169,24 +241,7 @@ STDMETHODIMP CFSDrives::BindToParentFolder(IFolderFolder **resultFolder)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::GetNumberOfProperties(UInt32 *numProperties)
|
||||
{
|
||||
*numProperties = sizeof(kProperties) / sizeof(kProperties[0]);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::GetPropertyInfo(UInt32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
{
|
||||
if (index >= sizeof(kProperties) / sizeof(kProperties[0]))
|
||||
return E_INVALIDARG;
|
||||
const STATPROPSTG &prop = kProperties[index];
|
||||
*propID = prop.propid;
|
||||
*varType = prop.vt;
|
||||
*name = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IMP_IFolderFolder_Props(CFSDrives)
|
||||
|
||||
STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
@@ -195,14 +250,20 @@ STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value)
|
||||
switch(propID)
|
||||
{
|
||||
case kpidType: prop = L"FSDrives"; break;
|
||||
case kpidPath: prop = LangString(IDS_COMPUTER, 0x03020300) + UString(WCHAR_PATH_SEPARATOR); break;
|
||||
case kpidPath:
|
||||
if (_volumeMode)
|
||||
prop = kVolPrefix;
|
||||
else
|
||||
prop = LangString(IDS_COMPUTER, 0x03020300) + UString(WCHAR_PATH_SEPARATOR);
|
||||
break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, INT32 *iconIndex)
|
||||
|
||||
STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
|
||||
{
|
||||
*iconIndex = 0;
|
||||
const CDriveInfo &di = _drives[index];
|
||||
@@ -215,3 +276,145 @@ STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, INT32 *iconIndex)
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
UString CFSDrives::GetExt(int index) const
|
||||
{
|
||||
const CDriveInfo &di = _drives[index];
|
||||
const wchar_t *ext = NULL;
|
||||
if (di.DriveType == DRIVE_CDROM)
|
||||
ext = L"iso";
|
||||
else if (di.FileSystemName.Find(L"NTFS") >= 0)
|
||||
ext = L"ntfs";
|
||||
else if (di.FileSystemName.Find(L"FAT") >= 0)
|
||||
ext = L"fat";
|
||||
else
|
||||
ext = L"img";
|
||||
return (UString)L'.' + ext;
|
||||
}
|
||||
|
||||
HRESULT CFSDrives::GetLength(int index, UInt64 &length) const
|
||||
{
|
||||
NFile::NIO::CInFile inFile;
|
||||
if (!inFile.Open(_drives[index].GetDeviceFileIoName()))
|
||||
return GetLastError();
|
||||
if (!inFile.LengthDefined)
|
||||
return E_FAIL;
|
||||
length = inFile.Length;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems,
|
||||
const wchar_t *path, IFolderOperationsExtractCallback *callback)
|
||||
{
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
|
||||
if (!_volumeMode)
|
||||
return E_NOTIMPL;
|
||||
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
const CDriveInfo &di = _drives[indices[i]];
|
||||
if (di.KnownSizes)
|
||||
totalSize += di.DriveSize;
|
||||
}
|
||||
RINOK(callback->SetTotal(totalSize));
|
||||
RINOK(callback->SetNumFiles(numItems));
|
||||
|
||||
UString destPath = path;
|
||||
if (destPath.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR);
|
||||
if (directName)
|
||||
{
|
||||
if (numItems > 1)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
UInt64 completedSize = 0;
|
||||
RINOK(callback->SetCompleted(&completedSize));
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
int index = indices[i];
|
||||
const CDriveInfo &di = _drives[index];
|
||||
UString destPath2 = destPath;
|
||||
UString name = di.Name;
|
||||
if (!directName)
|
||||
{
|
||||
UString destName = name;
|
||||
if (!destName.IsEmpty() && destName[destName.Length() - 1] == L':')
|
||||
{
|
||||
destName.Delete(destName.Length() - 1);
|
||||
destName += GetExt(index);
|
||||
}
|
||||
destPath2 += destName;
|
||||
}
|
||||
UString srcPath = di.GetDeviceFileIoName();
|
||||
|
||||
UInt64 fileSize = 0;
|
||||
if (GetLength(index, fileSize) != S_OK)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
if (!di.KnownSizes)
|
||||
totalSize += fileSize;
|
||||
RINOK(callback->SetTotal(totalSize));
|
||||
|
||||
Int32 writeAskResult;
|
||||
CMyComBSTR destPathResult;
|
||||
RINOK(callback->AskWrite(srcPath, BoolToInt(false), NULL, &fileSize,
|
||||
destPath2, &destPathResult, &writeAskResult));
|
||||
if (!IntToBool(writeAskResult))
|
||||
continue;
|
||||
|
||||
RINOK(callback->SetCurrentFilePath(srcPath));
|
||||
|
||||
static const UInt32 kBufferSize = (4 << 20);
|
||||
UInt32 bufferSize = (di.DriveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize;
|
||||
RINOK(CopyFileSpec(srcPath, destPathResult, false, fileSize, bufferSize, completedSize, callback));
|
||||
completedSize += fileSize;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::MoveTo(
|
||||
const UInt32 * /* indices */,
|
||||
UInt32 /* numItems */,
|
||||
const wchar_t * /* path */,
|
||||
IFolderOperationsExtractCallback * /* callback */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::CopyFrom(const wchar_t * /* fromFolderPath */,
|
||||
const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::CreateFile(const wchar_t * /* name */, IProgress * /* progress */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::Rename(UInt32 /* index */, const wchar_t * /* newName */, IProgress * /* progress */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::Delete(const UInt32 * /* indices */, UInt32 /* numItems */, IProgress * /* progress */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFSDrives::SetProperty(UInt32 /* index */, PROPID /* propID */,
|
||||
const PROPVARIANT * /* value */, IProgress * /* progress */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user