mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 15:14:59 -06:00
665 lines
17 KiB
C++
Executable File
665 lines
17 KiB
C++
Executable File
// FSFolder.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "FSFolder.h"
|
|
|
|
#include "Common/StringConvert.h"
|
|
#include "Common/UTFConvert.h"
|
|
#include "Common/ComTry.h"
|
|
|
|
#include "Windows/Defs.h"
|
|
#include "Windows/PropVariant.h"
|
|
#include "Windows/FileDir.h"
|
|
#include "Windows/FileIO.h"
|
|
|
|
#include "../../PropID.h"
|
|
|
|
#include "SysIconUtils.h"
|
|
#include "FSDrives.h"
|
|
#include "NetFolder.h"
|
|
|
|
namespace NWindows {
|
|
namespace NFile {
|
|
|
|
bool GetLongPath(LPCWSTR path, UString &longPath);
|
|
|
|
}}
|
|
|
|
using namespace NWindows;
|
|
using namespace NFile;
|
|
using namespace NFind;
|
|
|
|
namespace NFsFolder {
|
|
|
|
static STATPROPSTG kProperties[] =
|
|
{
|
|
{ NULL, kpidName, VT_BSTR},
|
|
// { NULL, kpidIsDir, VT_BOOL},
|
|
{ NULL, kpidSize, VT_UI8},
|
|
{ NULL, kpidMTime, VT_FILETIME},
|
|
{ NULL, kpidCTime, VT_FILETIME},
|
|
{ NULL, kpidATime, VT_FILETIME},
|
|
{ NULL, kpidAttrib, VT_UI4},
|
|
{ NULL, kpidPackSize, VT_UI8},
|
|
{ NULL, kpidComment, VT_BSTR},
|
|
{ NULL, kpidPrefix, VT_BSTR}
|
|
};
|
|
|
|
HRESULT CFSFolder::Init(const UString &path, IFolderFolder *parentFolder)
|
|
{
|
|
_parentFolder = parentFolder;
|
|
_path = path;
|
|
|
|
_findChangeNotification.FindFirst(_path, false,
|
|
FILE_NOTIFY_CHANGE_FILE_NAME |
|
|
FILE_NOTIFY_CHANGE_DIR_NAME |
|
|
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
|
FILE_NOTIFY_CHANGE_SIZE |
|
|
FILE_NOTIFY_CHANGE_LAST_WRITE /*|
|
|
FILE_NOTIFY_CHANGE_LAST_ACCESS |
|
|
FILE_NOTIFY_CHANGE_CREATION |
|
|
FILE_NOTIFY_CHANGE_SECURITY */);
|
|
if (!_findChangeNotification.IsHandleAllocated())
|
|
{
|
|
DWORD lastError = GetLastError();
|
|
CFindFile findFile;
|
|
CFileInfoW fileInfo;
|
|
if (!findFile.FindFirst(_path + UString(L"*"), fileInfo))
|
|
return lastError;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT GetFolderSize(const UString &path, UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress)
|
|
{
|
|
RINOK(progress->SetCompleted(NULL));
|
|
numFiles = numFolders = size = 0;
|
|
CEnumeratorW enumerator(path + UString(WSTRING_PATH_SEPARATOR L"*"));
|
|
CFileInfoW fileInfo;
|
|
while (enumerator.Next(fileInfo))
|
|
{
|
|
if (fileInfo.IsDir())
|
|
{
|
|
UInt64 subFolders, subFiles, subSize;
|
|
RINOK(GetFolderSize(path + UString(WCHAR_PATH_SEPARATOR) + fileInfo.Name, subFolders, subFiles, subSize, progress));
|
|
numFolders += subFolders;
|
|
numFolders++;
|
|
numFiles += subFiles;
|
|
size += subSize;
|
|
}
|
|
else
|
|
{
|
|
numFiles++;
|
|
size += fileInfo.Size;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFSFolder::LoadSubItems(CDirItem &dirItem, const UString &path)
|
|
{
|
|
{
|
|
CEnumeratorW enumerator(path + L"*");
|
|
CDirItem fileInfo;
|
|
while (enumerator.Next(fileInfo))
|
|
{
|
|
fileInfo.CompressedSizeIsDefined = false;
|
|
/*
|
|
if (!GetCompressedFileSize(_path + fileInfo.Name,
|
|
fileInfo.CompressedSize))
|
|
fileInfo.CompressedSize = fileInfo.Size;
|
|
*/
|
|
if (fileInfo.IsDir())
|
|
{
|
|
// fileInfo.Size = GetFolderSize(_path + fileInfo.Name);
|
|
fileInfo.Size = 0;
|
|
}
|
|
dirItem.Files.Add(fileInfo);
|
|
}
|
|
}
|
|
if (!_flatMode)
|
|
return S_OK;
|
|
|
|
for (int i = 0; i < dirItem.Files.Size(); i++)
|
|
{
|
|
CDirItem &item = dirItem.Files[i];
|
|
if (item.IsDir())
|
|
LoadSubItems(item, path + item.Name + WCHAR_PATH_SEPARATOR);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
void CFSFolder::AddRefs(CDirItem &dirItem)
|
|
{
|
|
int i;
|
|
for (i = 0; i < dirItem.Files.Size(); i++)
|
|
{
|
|
CDirItem &item = dirItem.Files[i];
|
|
item.Parent = &dirItem;
|
|
_refs.Add(&item);
|
|
}
|
|
if (!_flatMode)
|
|
return;
|
|
for (i = 0; i < dirItem.Files.Size(); i++)
|
|
{
|
|
CDirItem &item = dirItem.Files[i];
|
|
if (item.IsDir())
|
|
AddRefs(item);
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::LoadItems()
|
|
{
|
|
// OutputDebugString(TEXT("Start\n"));
|
|
INT32 dummy;
|
|
WasChanged(&dummy);
|
|
Clear();
|
|
RINOK(LoadSubItems(_root, _path));
|
|
AddRefs(_root);
|
|
|
|
// OutputDebugString(TEXT("Finish\n"));
|
|
_commentsAreLoaded = false;
|
|
return S_OK;
|
|
}
|
|
|
|
static const wchar_t *kDescriptionFileName = L"descript.ion";
|
|
|
|
bool CFSFolder::LoadComments()
|
|
{
|
|
if (_commentsAreLoaded)
|
|
return true;
|
|
_comments.Clear();
|
|
_commentsAreLoaded = true;
|
|
NIO::CInFile file;
|
|
if (!file.Open(_path + kDescriptionFileName))
|
|
return false;
|
|
UInt64 length;
|
|
if (!file.GetLength(length))
|
|
return false;
|
|
if (length >= (1 << 28))
|
|
return false;
|
|
AString s;
|
|
char *p = s.GetBuffer((int)((size_t)length + 1));
|
|
UInt32 processedSize;
|
|
file.Read(p, (UInt32)length, processedSize);
|
|
p[length] = 0;
|
|
s.ReleaseBuffer();
|
|
if (processedSize != length)
|
|
return false;
|
|
file.Close();
|
|
UString unicodeString;
|
|
if (!ConvertUTF8ToUnicode(s, unicodeString))
|
|
return false;
|
|
return _comments.ReadFromString(unicodeString);
|
|
}
|
|
|
|
static bool IsAscii(const UString &testString)
|
|
{
|
|
for (int i = 0; i < testString.Length(); i++)
|
|
if (testString[i] >= 0x80)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
bool CFSFolder::SaveComments()
|
|
{
|
|
NIO::COutFile file;
|
|
if (!file.Create(_path + kDescriptionFileName, true))
|
|
return false;
|
|
UString unicodeString;
|
|
_comments.SaveToString(unicodeString);
|
|
AString utfString;
|
|
ConvertUnicodeToUTF8(unicodeString, utfString);
|
|
UInt32 processedSize;
|
|
if (!IsAscii(unicodeString))
|
|
{
|
|
Byte bom [] = { 0xEF, 0xBB, 0xBF, 0x0D, 0x0A };
|
|
file.Write(bom , sizeof(bom), processedSize);
|
|
}
|
|
file.Write(utfString, utfString.Length(), processedSize);
|
|
_commentsAreLoaded = false;
|
|
return true;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::GetNumberOfItems(UInt32 *numItems)
|
|
{
|
|
*numItems = _refs.Size();
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
STDMETHODIMP CFSFolder::GetNumberOfSubFolders(UInt32 *numSubFolders)
|
|
{
|
|
UInt32 numSubFoldersLoc = 0;
|
|
for (int i = 0; i < _files.Size(); i++)
|
|
if (_files[i].IsDir())
|
|
numSubFoldersLoc++;
|
|
*numSubFolders = numSubFoldersLoc;
|
|
return S_OK;
|
|
}
|
|
*/
|
|
|
|
bool MyGetCompressedFileSizeW(LPCWSTR fileName, UInt64 &size)
|
|
{
|
|
DWORD highPart;
|
|
DWORD lowPart = ::GetCompressedFileSizeW(fileName, &highPart);
|
|
if (lowPart == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR)
|
|
{
|
|
#ifdef WIN_LONG_PATH
|
|
{
|
|
UString longPath;
|
|
if (GetLongPath(fileName, longPath))
|
|
lowPart = ::GetCompressedFileSizeW(longPath, &highPart);
|
|
}
|
|
#endif
|
|
if (lowPart == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR)
|
|
return false;
|
|
}
|
|
size = (UInt64(highPart) << 32) | lowPart;
|
|
return true;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)
|
|
{
|
|
NCOM::CPropVariant prop;
|
|
if (itemIndex >= (UInt32)_refs.Size())
|
|
return E_INVALIDARG;
|
|
CDirItem &fileInfo = *_refs[itemIndex];
|
|
switch(propID)
|
|
{
|
|
case kpidIsDir: prop = fileInfo.IsDir(); break;
|
|
case kpidName: prop = fileInfo.Name; break;
|
|
case kpidSize: if (!fileInfo.IsDir()) prop = fileInfo.Size; break;
|
|
case kpidPackSize:
|
|
if (!fileInfo.CompressedSizeIsDefined)
|
|
{
|
|
fileInfo.CompressedSizeIsDefined = true;
|
|
if (fileInfo.IsDir () ||
|
|
!MyGetCompressedFileSizeW(_path + GetRelPath(fileInfo), fileInfo.CompressedSize))
|
|
fileInfo.CompressedSize = fileInfo.Size;
|
|
}
|
|
prop = fileInfo.CompressedSize;
|
|
break;
|
|
case kpidAttrib: prop = (UInt32)fileInfo.Attrib; break;
|
|
case kpidCTime: prop = fileInfo.CTime; break;
|
|
case kpidATime: prop = fileInfo.ATime; break;
|
|
case kpidMTime: prop = fileInfo.MTime; break;
|
|
case kpidComment:
|
|
{
|
|
LoadComments();
|
|
UString comment;
|
|
if (_comments.GetValue(GetRelPath(fileInfo), comment))
|
|
prop = comment;
|
|
break;
|
|
}
|
|
case kpidPrefix:
|
|
{
|
|
if (_flatMode)
|
|
{
|
|
prop = GetPrefix(fileInfo);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
prop.Detach(value);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFSFolder::BindToFolderSpec(const wchar_t *name, IFolderFolder **resultFolder)
|
|
{
|
|
*resultFolder = 0;
|
|
CFSFolder *folderSpec = new CFSFolder;
|
|
CMyComPtr<IFolderFolder> subFolder = folderSpec;
|
|
RINOK(folderSpec->Init(_path + name + UString(WCHAR_PATH_SEPARATOR), 0));
|
|
*resultFolder = subFolder.Detach();
|
|
return S_OK;
|
|
}
|
|
|
|
UString CFSFolder::GetPrefix(const CDirItem &item) const
|
|
{
|
|
UString path;
|
|
CDirItem *cur = item.Parent;
|
|
while (cur->Parent != 0)
|
|
{
|
|
path = cur->Name + UString(WCHAR_PATH_SEPARATOR) + path;
|
|
cur = cur->Parent;
|
|
}
|
|
return path;
|
|
}
|
|
|
|
UString CFSFolder::GetRelPath(const CDirItem &item) const
|
|
{
|
|
return GetPrefix(item) + item.Name;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
|
|
{
|
|
*resultFolder = 0;
|
|
const CDirItem &fileInfo = *_refs[index];
|
|
if (!fileInfo.IsDir())
|
|
return E_INVALIDARG;
|
|
return BindToFolderSpec(GetRelPath(fileInfo), resultFolder);
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
|
|
{
|
|
return BindToFolderSpec(name, resultFolder);
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder)
|
|
{
|
|
*resultFolder = 0;
|
|
if (_parentFolder)
|
|
{
|
|
CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
|
|
*resultFolder = parentFolder.Detach();
|
|
return S_OK;
|
|
}
|
|
if (_path.IsEmpty())
|
|
return E_INVALIDARG;
|
|
int pos = _path.ReverseFind(WCHAR_PATH_SEPARATOR);
|
|
if (pos < 0 || pos != _path.Length() - 1)
|
|
return E_FAIL;
|
|
UString parentPath = _path.Left(pos);
|
|
pos = parentPath.ReverseFind(WCHAR_PATH_SEPARATOR);
|
|
if (pos < 0)
|
|
{
|
|
parentPath.Empty();
|
|
CFSDrives *drivesFolderSpec = new CFSDrives;
|
|
CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;
|
|
drivesFolderSpec->Init();
|
|
*resultFolder = drivesFolder.Detach();
|
|
return S_OK;
|
|
}
|
|
UString parentPathReduced = parentPath.Left(pos);
|
|
parentPath = parentPath.Left(pos + 1);
|
|
pos = parentPathReduced.ReverseFind(WCHAR_PATH_SEPARATOR);
|
|
if (pos == 1)
|
|
{
|
|
if (parentPath[0] != WCHAR_PATH_SEPARATOR)
|
|
return E_FAIL;
|
|
CNetFolder *netFolderSpec = new CNetFolder;
|
|
CMyComPtr<IFolderFolder> netFolder = netFolderSpec;
|
|
netFolderSpec->Init(parentPath);
|
|
*resultFolder = netFolder.Detach();
|
|
return S_OK;
|
|
}
|
|
CFSFolder *parentFolderSpec = new CFSFolder;
|
|
CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec;
|
|
RINOK(parentFolderSpec->Init(parentPath, 0));
|
|
*resultFolder = parentFolder.Detach();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::GetNumberOfProperties(UInt32 *numProperties)
|
|
{
|
|
*numProperties = sizeof(kProperties) / sizeof(kProperties[0]);
|
|
if (!_flatMode)
|
|
(*numProperties)--;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::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 CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
|
|
{
|
|
COM_TRY_BEGIN
|
|
NWindows::NCOM::CPropVariant prop;
|
|
switch(propID)
|
|
{
|
|
case kpidType: prop = L"FSFolder"; break;
|
|
case kpidPath: prop = _path; break;
|
|
}
|
|
prop.Detach(value);
|
|
return S_OK;
|
|
COM_TRY_END
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::WasChanged(INT32 *wasChanged)
|
|
{
|
|
bool wasChangedMain = false;
|
|
for (;;)
|
|
{
|
|
if (!_findChangeNotification.IsHandleAllocated())
|
|
{
|
|
*wasChanged = BoolToInt(false);
|
|
return S_OK;
|
|
}
|
|
|
|
DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
|
|
bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
|
|
if (wasChangedLoc)
|
|
{
|
|
_findChangeNotification.FindNext();
|
|
wasChangedMain = true;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
*wasChanged = BoolToInt(wasChangedMain);
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::Clone(IFolderFolder **resultFolder)
|
|
{
|
|
CFSFolder *fsFolderSpec = new CFSFolder;
|
|
CMyComPtr<IFolderFolder> folderNew = fsFolderSpec;
|
|
fsFolderSpec->Init(_path, 0);
|
|
*resultFolder = folderNew.Detach();
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFSFolder::GetItemsFullSize(const UInt32 *indices, UInt32 numItems,
|
|
UInt64 &numFolders, UInt64 &numFiles, UInt64 &size, IProgress *progress)
|
|
{
|
|
numFiles = numFolders = size = 0;
|
|
UInt32 i;
|
|
for (i = 0; i < numItems; i++)
|
|
{
|
|
int index = indices[i];
|
|
if (index >= _refs.Size())
|
|
return E_INVALIDARG;
|
|
const CDirItem &fileInfo = *_refs[index];
|
|
if (fileInfo.IsDir())
|
|
{
|
|
UInt64 subFolders, subFiles, subSize;
|
|
RINOK(GetFolderSize(_path + GetRelPath(fileInfo), subFolders, subFiles, subSize, progress));
|
|
numFolders += subFolders;
|
|
numFolders++;
|
|
numFiles += subFiles;
|
|
size += subSize;
|
|
}
|
|
else
|
|
{
|
|
numFiles++;
|
|
size += fileInfo.Size;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFSFolder::GetItemFullSize(int index, UInt64 &size, IProgress *progress)
|
|
{
|
|
const CDirItem &fileInfo = *_refs[index];
|
|
if (fileInfo.IsDir())
|
|
{
|
|
/*
|
|
CMyComPtr<IFolderFolder> subFolder;
|
|
RINOK(BindToFolder(index, &subFolder));
|
|
CMyComPtr<IFolderReload> aFolderReload;
|
|
subFolder.QueryInterface(&aFolderReload);
|
|
aFolderReload->Reload();
|
|
UInt32 numItems;
|
|
RINOK(subFolder->GetNumberOfItems(&numItems));
|
|
CMyComPtr<IFolderGetItemFullSize> aGetItemFullSize;
|
|
subFolder.QueryInterface(&aGetItemFullSize);
|
|
for (UInt32 i = 0; i < numItems; i++)
|
|
{
|
|
UInt64 size;
|
|
RINOK(aGetItemFullSize->GetItemFullSize(i, &size));
|
|
*totalSize += size;
|
|
}
|
|
*/
|
|
UInt64 numFolders, numFiles;
|
|
return GetFolderSize(_path + GetRelPath(fileInfo), numFolders, numFiles, size, progress);
|
|
}
|
|
size = fileInfo.Size;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::GetItemFullSize(UInt32 index, PROPVARIANT *value, IProgress *progress)
|
|
{
|
|
NCOM::CPropVariant prop;
|
|
if (index >= (UInt32)_refs.Size())
|
|
return E_INVALIDARG;
|
|
UInt64 size = 0;
|
|
HRESULT result = GetItemFullSize(index, size, progress);
|
|
prop = size;
|
|
prop.Detach(value);
|
|
return result;
|
|
}
|
|
|
|
HRESULT CFSFolder::GetComplexName(const wchar_t *name, UString &resultPath)
|
|
{
|
|
UString newName = name;
|
|
resultPath = _path + newName;
|
|
if (newName.Length() < 1)
|
|
return S_OK;
|
|
if (newName[0] == WCHAR_PATH_SEPARATOR)
|
|
{
|
|
resultPath = newName;
|
|
return S_OK;
|
|
}
|
|
if (newName.Length() < 2)
|
|
return S_OK;
|
|
if (newName[1] == L':')
|
|
resultPath = newName;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::CreateFolder(const wchar_t *name, IProgress * /* progress */)
|
|
{
|
|
UString processedName;
|
|
RINOK(GetComplexName(name, processedName));
|
|
if(NDirectory::MyCreateDirectory(processedName))
|
|
return S_OK;
|
|
if(::GetLastError() == ERROR_ALREADY_EXISTS)
|
|
return ::GetLastError();
|
|
if (!NDirectory::CreateComplexDirectory(processedName))
|
|
return ::GetLastError();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::CreateFile(const wchar_t *name, IProgress * /* progress */)
|
|
{
|
|
UString processedName;
|
|
RINOK(GetComplexName(name, processedName));
|
|
NIO::COutFile outFile;
|
|
if (!outFile.Create(processedName, false))
|
|
return ::GetLastError();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */)
|
|
{
|
|
const CDirItem &fileInfo = *_refs[index];
|
|
const UString fullPrefix = _path + GetPrefix(fileInfo);
|
|
if (!NDirectory::MyMoveFile(fullPrefix + fileInfo.Name, fullPrefix + newName))
|
|
return GetLastError();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress *progress)
|
|
{
|
|
RINOK(progress->SetTotal(numItems));
|
|
for (UInt32 i = 0; i < numItems; i++)
|
|
{
|
|
const CDirItem &fileInfo = *_refs[indices[i]];
|
|
const UString fullPath = _path + GetRelPath(fileInfo);
|
|
bool result;
|
|
if (fileInfo.IsDir())
|
|
result = NDirectory::RemoveDirectoryWithSubItems(fullPath);
|
|
else
|
|
result = NDirectory::DeleteFileAlways(fullPath);
|
|
if (!result)
|
|
return GetLastError();
|
|
UInt64 completed = i;
|
|
RINOK(progress->SetCompleted(&completed));
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID,
|
|
const PROPVARIANT *value, IProgress * /* progress */)
|
|
{
|
|
if (index >= (UInt32)_refs.Size())
|
|
return E_INVALIDARG;
|
|
CDirItem &fileInfo = *_refs[index];
|
|
if (fileInfo.Parent->Parent != 0)
|
|
return E_NOTIMPL;
|
|
switch(propID)
|
|
{
|
|
case kpidComment:
|
|
{
|
|
UString filename = fileInfo.Name;
|
|
filename.Trim();
|
|
if (value->vt == VT_EMPTY)
|
|
_comments.DeletePair(filename);
|
|
else if (value->vt == VT_BSTR)
|
|
{
|
|
CTextPair pair;
|
|
pair.ID = filename;
|
|
pair.ID.Trim();
|
|
pair.Value = value->bstrVal;
|
|
pair.Value.Trim();
|
|
if (pair.Value.IsEmpty())
|
|
_comments.DeletePair(filename);
|
|
else
|
|
_comments.AddPair(pair);
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
SaveComments();
|
|
break;
|
|
}
|
|
default:
|
|
return E_NOTIMPL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::GetSystemIconIndex(UInt32 index, INT32 *iconIndex)
|
|
{
|
|
if (index >= (UInt32)_refs.Size())
|
|
return E_INVALIDARG;
|
|
const CDirItem &fileInfo = *_refs[index];
|
|
*iconIndex = 0;
|
|
int iconIndexTemp;
|
|
if (GetRealIconIndex(_path + GetRelPath(fileInfo), fileInfo.Attrib, iconIndexTemp) != 0)
|
|
{
|
|
*iconIndex = iconIndexTemp;
|
|
return S_OK;
|
|
}
|
|
return GetLastError();
|
|
}
|
|
|
|
STDMETHODIMP CFSFolder::SetFlatMode(Int32 flatMode)
|
|
{
|
|
_flatMode = IntToBool(flatMode);
|
|
return S_OK;
|
|
}
|
|
|
|
}
|