mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 15:14:59 -06:00
296 lines
7.6 KiB
C++
Executable File
296 lines
7.6 KiB
C++
Executable File
// PhysDriveFolder.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "../../../../C/Alloc.h"
|
|
|
|
#include "Common/Buffer.h"
|
|
|
|
#include "Windows/PropVariant.h"
|
|
#include "Windows/FileDevice.h"
|
|
#include "Windows/FileSystem.h"
|
|
|
|
#include "../../PropID.h"
|
|
|
|
#include "PhysDriveFolder.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 prop;
|
|
if (itemIndex >= 1)
|
|
return E_INVALIDARG;
|
|
switch(propID)
|
|
{
|
|
case kpidIsDir: prop = false; break;
|
|
case kpidName: prop = _name; break;
|
|
case kpidSize: prop = _length; break;
|
|
}
|
|
prop.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 prop;
|
|
if (index >= 1)
|
|
return E_INVALIDARG;
|
|
UInt64 size = 0;
|
|
HRESULT result = GetLength(size);
|
|
prop = size;
|
|
prop.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, 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 = MyAlloc(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;
|
|
}
|
|
|
|
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] != WCHAR_PATH_SEPARATOR);
|
|
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, 0, 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, 0, callback);
|
|
}
|
|
|