Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2009-06-02 04:00:00 +0400
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:59 +0300
commit829409452d85cd6dd9dfc9151f109d6e13a2bb1c (patch)
treee0acaea47044d167f35fa197584dee1bde41c329 /CPP/7zip/UI/FileManager/FSDrives.cpp
parent8874e4fbc9faabdcff719b9b2ac8ebad4f282bbe (diff)
9.04 beta
Diffstat (limited to 'CPP/7zip/UI/FileManager/FSDrives.cpp')
-rwxr-xr-xCPP/7zip/UI/FileManager/FSDrives.cpp309
1 files changed, 256 insertions, 53 deletions
diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp
index f2d7ac93..87ee3fc9 100755
--- a/CPP/7zip/UI/FileManager/FSDrives.cpp
+++ b/CPP/7zip/UI/FileManager/FSDrives.cpp
@@ -2,48 +2,118 @@
#include "StdAfx.h"
-#include "resource.h"
-
-#include "FSDrives.h"
+#include "../../../../C/Alloc.h"
-#include "Common/StringConvert.h"
#include "Common/ComTry.h"
-#include "../../PropID.h"
+#include "Common/StringConvert.h"
+
#include "Windows/Defs.h"
-#include "Windows/PropVariant.h"
#include "Windows/FileDir.h"
+#include "Windows/FileIO.h"
#include "Windows/FileSystem.h"
+#include "Windows/PropVariant.h"
-#include "SysIconUtils.h"
+#include "../../PropID.h"
+
+#include "FSDrives.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
+{
+ return kVolPrefix + Name;
+}
+
+struct CPhysTempBuffer
+{
+ void *buffer;
+ CPhysTempBuffer(): buffer(0) {}
+ ~CPhysTempBuffer() { MidFree(buffer); }
+};
+
+static HRESULT CopyFileSpec(LPCWSTR fromPath, LPCWSTR toPath, bool writeToDisk, UInt64 fileSize,
+ UInt32 bufferSize, UInt64 progressStart, IProgress *progress)
+{
+ 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, kpidIsDir, VT_BOOL},
- { L"Total Size", kpidTotalSize, VT_UI8},
- { L"Free Space", kpidFreeSpace, VT_UI8},
+ { NULL, kpidTotalSize, VT_UI8},
+ { NULL, kpidFreeSpace, VT_UI8},
{ NULL, kpidType, VT_BSTR},
- { L"Label", kpidVolumeName, VT_BSTR},
- { L"File system", kpidFileSystem, VT_BSTR},
- { L"Cluster Size", kpidClusterSize, VT_UI8}
+ { NULL, kpidVolumeName, VT_BSTR},
+ { NULL, kpidFileSystem, VT_BSTR},
+ { NULL, kpidClusterSize, VT_UI8}
};
-static const wchar_t *kDriveTypes[] =
+static const char *kDriveTypes[] =
{
- L"Unknown",
- L"No Root Dir",
- L"Removable",
- L"Fixed",
- L"Remote",
- L"CD-ROM",
- L"RAM disk"
+ "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;
+}