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:
Diffstat (limited to 'CPP/7zip/UI/FileManager/PhysDriveFolder.cpp')
-rwxr-xr-xCPP/7zip/UI/FileManager/PhysDriveFolder.cpp299
1 files changed, 299 insertions, 0 deletions
diff --git a/CPP/7zip/UI/FileManager/PhysDriveFolder.cpp b/CPP/7zip/UI/FileManager/PhysDriveFolder.cpp
new file mode 100755
index 00000000..d611e096
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PhysDriveFolder.cpp
@@ -0,0 +1,299 @@
+// PhysDriveFolder.cpp
+
+#include "StdAfx.h"
+
+extern "C"
+{
+ #include "../../../../C/Alloc.h"
+}
+
+#include "PhysDriveFolder.h"
+#include "Windows/PropVariant.h"
+#include "Windows/FileDevice.h"
+#include "Windows/FileSystem.h"
+
+#include "../../PropID.h"
+
+using namespace NWindows;
+
+static const UInt32 kBufferSize = (4 << 20);
+
+static STATPROPSTG kProperties[] =
+{
+ { NULL, kpidName, VT_BSTR},
+ { NULL, kpidSize, VT_UI8}
+};
+
+HRESULT CPhysDriveFolder::Init(const UString &path)
+{
+ _prefix = L"\\\\.\\";
+ _path = path;
+ NFile::NDevice::CInFile inFile;
+ if (!inFile.Open(GetFullPath()))
+ return GetLastError();
+ return S_OK;
+}
+
+STDMETHODIMP CPhysDriveFolder::LoadItems()
+{
+ _driveType = NFile::NSystem::MyGetDriveType(_path + L"\\");
+ _name = _path.Left(1);
+ _name += L'.';
+ if (_driveType == DRIVE_CDROM)
+ _name += L"iso";
+ else
+ _name += L"img";
+ Int32 dummy;
+ WasChanged(&dummy);
+ return GetLength(_length);
+}
+
+STDMETHODIMP CPhysDriveFolder::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = 1;
+ return S_OK;
+}
+
+STDMETHODIMP CPhysDriveFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant propVariant;
+ if (itemIndex >= 1)
+ return E_INVALIDARG;
+ switch(propID)
+ {
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidName:
+ propVariant = _name;
+ break;
+ case kpidSize:
+ propVariant = _length;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
+
+STDMETHODIMP CPhysDriveFolder::BindToFolder(UInt32 /* index */, IFolderFolder ** /* resultFolder */)
+ { return E_NOTIMPL; }
+
+STDMETHODIMP CPhysDriveFolder::BindToFolder(const wchar_t * /* name */, IFolderFolder ** /* resultFolder */)
+ { return E_NOTIMPL; }
+
+STDMETHODIMP CPhysDriveFolder::BindToParentFolder(IFolderFolder **resultFolder)
+{
+ *resultFolder = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CPhysDriveFolder::GetNumberOfProperties(UInt32 *numProperties)
+{
+ *numProperties = sizeof(kProperties) / sizeof(kProperties[0]);
+ return S_OK;
+}
+
+STDMETHODIMP CPhysDriveFolder::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;
+}
+
+
+STDMETHODIMP CPhysDriveFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant prop;
+ switch(propID)
+ {
+ case kpidType: prop = L"PhysDrive"; break;
+ case kpidPath: prop = (GetFullPath() + L"\\"); break;
+ }
+ prop.Detach(value);
+ return S_OK;
+}
+
+STDMETHODIMP CPhysDriveFolder::WasChanged(Int32 *wasChanged)
+{
+ bool wasChangedMain = false;
+ *wasChanged = BoolToInt(wasChangedMain);
+ return S_OK;
+}
+
+STDMETHODIMP CPhysDriveFolder::Clone(IFolderFolder **resultFolder)
+{
+ CPhysDriveFolder *folderSpec = new CPhysDriveFolder;
+ CMyComPtr<IFolderFolder> folderNew = folderSpec;
+ folderSpec->Init(_path);
+ *resultFolder = folderNew.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CPhysDriveFolder::GetItemFullSize(UInt32 index, PROPVARIANT *value, IProgress * /* progress */)
+{
+ NCOM::CPropVariant propVariant;
+ if (index >= 1)
+ return E_INVALIDARG;
+ UInt64 size = 0;
+ HRESULT result = GetLength(size);
+ propVariant = size;
+ propVariant.Detach(value);
+ return result;
+}
+
+STDMETHODIMP CPhysDriveFolder::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */)
+ { return E_NOTIMPL; }
+
+STDMETHODIMP CPhysDriveFolder::CreateFile(const wchar_t * /* name */, IProgress * /* progress */)
+ { return E_NOTIMPL; }
+
+STDMETHODIMP CPhysDriveFolder::Rename(UInt32 /* index */, const wchar_t * /* newName */, IProgress * /* progress */)
+ { return E_NOTIMPL; }
+
+STDMETHODIMP CPhysDriveFolder::Delete(const UInt32 * /* indices */, UInt32 /* numItems */, IProgress * /* progress */)
+ { return E_NOTIMPL; }
+
+STDMETHODIMP CPhysDriveFolder::SetProperty(UInt32 index, PROPID /* propID */,
+ const PROPVARIANT * /* value */, IProgress * /* progress */)
+{
+ if (index >= 1)
+ return E_INVALIDARG;
+ return E_NOTIMPL;
+}
+
+HRESULT CPhysDriveFolder::GetLength(UInt64 &length) const
+{
+ NFile::NDevice::CInFile inFile;
+ if (!inFile.Open(GetFullPath()))
+ return GetLastError();
+ if (!inFile.GetLengthSmart(length))
+ return GetLastError();
+ return S_OK;
+}
+
+struct CPhysTempBuffer
+{
+ void *buffer;
+ CPhysTempBuffer(): buffer(0) {}
+ ~CPhysTempBuffer() { MyFree(buffer); }
+};
+
+HRESULT CopyFileSpec(LPCWSTR fromPath, LPCWSTR toPath, bool writeToDisk, UInt64 fileSize, UInt32 bufferSize, 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 = MyAlloc(bufferSize);
+ if (tempBuffer.buffer == 0)
+ return E_OUTOFMEMORY;
+
+ for (UInt64 pos = 0; pos < fileSize;)
+ {
+ RINOK(progress->SetCompleted(&pos));
+ 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;
+}
+
+STDMETHODIMP CPhysDriveFolder::CopyTo(const UInt32 * /* indices */, UInt32 numItems,
+ const wchar_t *path, IFolderOperationsExtractCallback *callback)
+{
+ if (numItems == 0)
+ return S_OK;
+ UString destPath = path;
+ if (destPath.IsEmpty())
+ return E_INVALIDARG;
+ bool directName = (destPath[destPath.Length() - 1] != L'\\');
+ if (directName)
+ {
+ if (numItems > 1)
+ return E_INVALIDARG;
+ }
+ else
+ destPath += _name;
+
+ UInt64 fileSize;
+ if (GetLength(fileSize) == S_OK)
+ {
+ RINOK(callback->SetTotal(fileSize));
+ }
+
+ Int32 writeAskResult;
+ CMyComBSTR destPathResult;
+ RINOK(callback->AskWrite(GetFullPath(), BoolToInt(false), NULL, &fileSize,
+ destPath, &destPathResult, &writeAskResult));
+ if (!IntToBool(writeAskResult))
+ return S_OK;
+
+ RINOK(callback->SetCurrentFilePath(GetFullPathWithName()));
+
+ UInt32 bufferSize = (_driveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize;
+ return CopyFileSpec(GetFullPath(), destPathResult, false, fileSize, bufferSize, callback);
+}
+
+/////////////////////////////////////////////////
+// Move Operations
+
+STDMETHODIMP CPhysDriveFolder::MoveTo(
+ const UInt32 * /* indices */,
+ UInt32 /* numItems */,
+ const wchar_t * /* path */,
+ IFolderOperationsExtractCallback * /* callback */)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CPhysDriveFolder::CopyFrom(
+ const wchar_t * fromFolderPath,
+ const wchar_t ** itemsPaths, UInt32 numItems, IProgress *callback)
+{
+ if (numItems == 0)
+ return S_OK;
+ if (numItems != 1)
+ return E_INVALIDARG;
+ if (_driveType != DRIVE_REMOVABLE /* && _driveType != DRIVE_CDROM */)
+ return E_NOTIMPL;
+ UInt32 bufferSize = (_driveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize;
+ // MessageBoxW(0, fromFolderPath, itemsPaths[0], 0);
+ return CopyFileSpec((UString)fromFolderPath + itemsPaths[0], GetFullPath(), true, (UInt64)(Int64)-1, bufferSize, callback);
+}