diff options
Diffstat (limited to 'CPP/7zip/FileManager/PhysDriveFolder.cpp')
-rwxr-xr-x | CPP/7zip/FileManager/PhysDriveFolder.cpp | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/CPP/7zip/FileManager/PhysDriveFolder.cpp b/CPP/7zip/FileManager/PhysDriveFolder.cpp new file mode 100755 index 00000000..b69d3cb3 --- /dev/null +++ b/CPP/7zip/FileManager/PhysDriveFolder.cpp @@ -0,0 +1,274 @@ +// PhysDriveFolder.cpp + +#include "StdAfx.h" + +#include "PhysDriveFolder.h" + +#include "Common/Alloc.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} +}; + +CPhysDriveFolder::~CPhysDriveFolder() +{ + if (_buffer != 0) + MyFree(_buffer); +} + +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::GetName(BSTR * /* name */) + { return E_NOTIMPL; } + +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::GetTypeID(BSTR *name) +{ + CMyComBSTR temp = L"PhysDrive"; + *name = temp.Detach(); + return S_OK; +} + +STDMETHODIMP CPhysDriveFolder::GetPath(BSTR *path) +{ + UString tempPath = GetFullPath() + L"\\"; + CMyComBSTR temp = tempPath; + *path = temp.Detach(); + 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; +} + +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())); + + NFile::NDevice::CInFile inFile; + if (!inFile.Open(GetFullPath())) + return GetLastError(); + NFile::NIO::COutFile outFile; + if (!outFile.Create(destPathResult, true)) + return GetLastError(); + if (_buffer == 0) + { + _buffer = MyAlloc(kBufferSize); + if (_buffer == 0) + return E_OUTOFMEMORY; + } + UInt64 pos = 0; + UInt32 bufferSize = kBufferSize; + if (_driveType == DRIVE_REMOVABLE) + bufferSize = (18 << 10) * 4; + pos = 0; + while(pos < fileSize) + { + RINOK(callback->SetCompleted(&pos)); + UInt32 curSize = (UInt32)MyMin(fileSize - pos, (UInt64)bufferSize); + UInt32 processedSize; + if (!inFile.Read(_buffer, curSize, processedSize)) + return GetLastError(); + if (processedSize == 0) + break; + curSize = processedSize; + if (!outFile.Write(_buffer, curSize, processedSize)) + return GetLastError(); + if (curSize != processedSize) + return E_FAIL; + pos += curSize; + } + return S_OK; +} + +///////////////////////////////////////////////// +// 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 * /* progress */) +{ + return E_NOTIMPL; +} |