diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2009-06-02 04:00:00 +0400 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:59 +0300 |
commit | 829409452d85cd6dd9dfc9151f109d6e13a2bb1c (patch) | |
tree | e0acaea47044d167f35fa197584dee1bde41c329 /CPP/7zip/UI/FileManager/FSDrives.cpp | |
parent | 8874e4fbc9faabdcff719b9b2ac8ebad4f282bbe (diff) |
9.04 beta
Diffstat (limited to 'CPP/7zip/UI/FileManager/FSDrives.cpp')
-rwxr-xr-x | CPP/7zip/UI/FileManager/FSDrives.cpp | 309 |
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; +} |