This commit is contained in:
Igor Pavlov
2015-06-15 00:00:00 +00:00
committed by Kornel Lesiński
parent 0713a3ab80
commit 54490d51d5
591 changed files with 34932 additions and 16390 deletions

View File

@@ -29,7 +29,7 @@ bool CAboutDialog::OnInit()
UString s = L"7-Zip " LLL(MY_VERSION);
#ifdef MY_CPU_64BIT
s += L" [";
s += LangString(IDS_PROP_BIT64);
AddLangString(s, IDS_PROP_BIT64);
s += L']';
#endif

View File

@@ -0,0 +1,839 @@
// AltStreamsFolder.cpp
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileIO.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/PropVariant.h"
#include "../Common/ExtractingFilePath.h"
#include "../Agent/IFolderArchive.h"
#include "AltStreamsFolder.h"
#include "FSDrives.h"
#include "FSFolder.h"
#include "SysIconUtils.h"
using namespace NWindows;
using namespace NFile;
using namespace NFind;
using namespace NDir;
using namespace NName;
#ifndef USE_UNICODE_FSTRING
int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2);
#endif
#ifndef UNDER_CE
namespace NFsFolder
{
bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size);
}
#endif
namespace NAltStreamsFolder {
static const Byte kProps[] =
{
kpidName,
kpidSize,
kpidPackSize
};
static unsigned GetFsParentPrefixSize(const FString &path)
{
if (IsNetworkShareRootPath(path))
return 0;
unsigned prefixSize = GetRootPrefixSize(path);
if (prefixSize == 0 || prefixSize >= path.Len())
return 0;
FString parentPath = path;
int pos = parentPath.ReverseFind_PathSepar();
if (pos < 0)
return 0;
if (pos == (int)parentPath.Len() - 1)
{
parentPath.DeleteBack();
pos = parentPath.ReverseFind_PathSepar();
if (pos < 0)
return 0;
}
if ((unsigned)pos + 1 < prefixSize)
return 0;
return pos + 1;
}
HRESULT CAltStreamsFolder::Init(const FString &path /* , IFolderFolder *parentFolder */)
{
// _parentFolder = parentFolder;
if (path.Back() != ':')
return E_FAIL;
_pathPrefix = path;
_pathBaseFile = path;
_pathBaseFile.DeleteBack();
{
CFileInfo fi;
if (!fi.Find(_pathBaseFile))
return GetLastError();
}
unsigned prefixSize = GetFsParentPrefixSize(_pathBaseFile);
if (prefixSize == 0)
return S_OK;
FString parentPath = _pathBaseFile;
parentPath.DeleteFrom(prefixSize);
_findChangeNotification.FindFirst(parentPath, 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())
return S_OK;
return GetLastError();
*/
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::LoadItems()
{
Int32 dummy;
WasChanged(&dummy);
Clear();
CStreamEnumerator enumerator(_pathBaseFile);
CStreamInfo si;
for (;;)
{
bool found;
if (!enumerator.Next(si, found))
{
// if (GetLastError() == ERROR_ACCESS_DENIED)
// break;
// return E_FAIL;
break;
}
if (!found)
break;
if (si.IsMainStream())
continue;
CAltStream ss;
ss.Name = si.GetReducedName();
if (!ss.Name.IsEmpty() && ss.Name[0] == ':')
ss.Name.Delete(0);
ss.Size = si.Size;
ss.PackSize_Defined = false;
ss.PackSize = si.Size;
Streams.Add(ss);
}
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::GetNumberOfItems(UInt32 *numItems)
{
*numItems = Streams.Size();
return S_OK;
}
#ifdef USE_UNICODE_FSTRING
STDMETHODIMP CAltStreamsFolder::GetItemPrefix(UInt32 /* index */, const wchar_t **name, unsigned *len)
{
*name = 0;
*len = 0;
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len)
{
*name = 0;
*len = 0;
{
const CAltStream &ss = Streams[index];
*name = ss.Name;
*len = ss.Name.Len();
}
return S_OK;
}
STDMETHODIMP_(UInt64) CAltStreamsFolder::GetItemSize(UInt32 index)
{
return Streams[index].Size;
}
#endif
STDMETHODIMP CAltStreamsFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
{
CAltStream &ss = Streams[index];
switch (propID)
{
case kpidIsDir: prop = false; break;
case kpidIsAltStream: prop = true; break;
case kpidName: prop = ss.Name; break;
case kpidSize: prop = ss.Size; break;
case kpidPackSize:
#ifdef UNDER_CE
prop = ss.Size;
#else
if (!ss.PackSize_Defined)
{
ss.PackSize_Defined = true;
if (!NFsFolder::MyGetCompressedFileSizeW(_pathPrefix + us2fs(ss.Name), ss.PackSize))
ss.PackSize = ss.Size;
}
prop = ss.PackSize;
#endif
break;
}
}
prop.Detach(value);
return S_OK;
}
// returns Position of extension including '.'
static inline const wchar_t *GetExtensionPtr(const UString &name)
{
int dotPos = name.ReverseFind_Dot();
return name.Ptr((dotPos < 0) ? name.Len() : dotPos);
}
STDMETHODIMP_(Int32) CAltStreamsFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 /* propIsRaw */)
{
const CAltStream &ss1 = Streams[index1];
const CAltStream &ss2 = Streams[index2];
switch (propID)
{
case kpidName:
{
return CompareFileNames_ForFolderList(ss1.Name, ss2.Name);
// return MyStringCompareNoCase(ss1.Name, ss2.Name);
}
case kpidSize:
return MyCompare(ss1.Size, ss2.Size);
case kpidPackSize:
{
#ifdef UNDER_CE
return MyCompare(ss1.Size, ss2.Size);
#else
// PackSize can be undefined here
return MyCompare(
ss1.PackSize,
ss2.PackSize);
#endif
}
case kpidExtension:
return CompareFileNames_ForFolderList(
GetExtensionPtr(ss1.Name),
GetExtensionPtr(ss2.Name));
}
return 0;
}
STDMETHODIMP CAltStreamsFolder::BindToFolder(UInt32 /* index */, IFolderFolder **resultFolder)
{
*resultFolder = 0;
return E_INVALIDARG;
}
STDMETHODIMP CAltStreamsFolder::BindToFolder(const wchar_t * /* name */, IFolderFolder **resultFolder)
{
*resultFolder = 0;
return E_INVALIDARG;
}
static const CFSTR kSuperPrefix = FTEXT("\\\\?\\");
STDMETHODIMP CAltStreamsFolder::BindToParentFolder(IFolderFolder **resultFolder)
{
*resultFolder = 0;
/*
if (_parentFolder)
{
CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
*resultFolder = parentFolder.Detach();
return S_OK;
}
*/
if (IsDriveRootPath_SuperAllowed(_pathBaseFile))
{
CFSDrives *drivesFolderSpec = new CFSDrives;
CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;
drivesFolderSpec->Init();
*resultFolder = drivesFolder.Detach();
return S_OK;
}
/*
parentPath.DeleteFrom(pos + 1);
if (parentPath == kSuperPrefix)
{
#ifdef UNDER_CE
*resultFolder = 0;
#else
CFSDrives *drivesFolderSpec = new CFSDrives;
CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;
drivesFolderSpec->Init(false, true);
*resultFolder = drivesFolder.Detach();
#endif
return S_OK;
}
FString parentPathReduced = parentPath.Left(pos);
#ifndef UNDER_CE
pos = parentPathReduced.ReverseFind_PathSepar();
if (pos == 1)
{
if (!IS_PATH_SEPAR_CHAR(parentPath[0]))
return E_FAIL;
CNetFolder *netFolderSpec = new CNetFolder;
CMyComPtr<IFolderFolder> netFolder = netFolderSpec;
netFolderSpec->Init(fs2us(parentPath));
*resultFolder = netFolder.Detach();
return S_OK;
}
#endif
CFSFolder *parentFolderSpec = new CFSFolder;
CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec;
RINOK(parentFolderSpec->Init(parentPath, 0));
*resultFolder = parentFolder.Detach();
*/
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::GetNumberOfProperties(UInt32 *numProperties)
{
*numProperties = ARRAY_SIZE(kProps);
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)
STDMETHODIMP CAltStreamsFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
switch (propID)
{
case kpidType: prop = "AltStreamsFolder"; break;
case kpidPath: prop = fs2us(_pathPrefix); break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CAltStreamsFolder::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 CAltStreamsFolder::Clone(IFolderFolder **resultFolder)
{
CAltStreamsFolder *folderSpec = new CAltStreamsFolder;
CMyComPtr<IFolderFolder> folderNew = folderSpec;
folderSpec->Init(_pathPrefix);
*resultFolder = folderNew.Detach();
return S_OK;
}
void CAltStreamsFolder::GetAbsPath(const wchar_t *name, FString &absPath)
{
absPath.Empty();
if (!IsAbsolutePath(name))
absPath += _pathPrefix;
absPath += us2fs(name);
}
static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
const wchar_t *message, const FString &fileName)
{
UString s = message;
s += L" : ";
s += fs2us(fileName);
return callback->ShowMessage(s);
}
static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback,
const wchar_t *message, const FString &fileName)
{
UString s = message;
s += L" : ";
s += fs2us(fileName);
return callback->UpdateErrorMessage(s);
}
static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
const char *message, const FString &fileName)
{
return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
}
/*
static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback,
const char *message, const FString &fileName)
{
return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
}
*/
STDMETHODIMP CAltStreamsFolder::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
STDMETHODIMP CAltStreamsFolder::CreateFile(const wchar_t *name, IProgress * /* progress */)
{
FString absPath;
GetAbsPath(name, absPath);
NIO::COutFile outFile;
if (!outFile.Create(absPath, false))
return ::GetLastError();
return S_OK;
}
static DWORD Return_LastError_or_FAIL()
{
DWORD errorCode = GetLastError();
if (errorCode == 0)
errorCode = (DWORD)E_FAIL;
return errorCode;
}
static UString GetLastErrorMessage()
{
return NError::MyFormatMessage(Return_LastError_or_FAIL());
}
static HRESULT UpdateFile(NFsFolder::CCopyStateIO &state, CFSTR inPath, CFSTR outPath, IFolderArchiveUpdateCallback *callback)
{
if (NFind::DoesFileOrDirExist(outPath))
{
RINOK(SendMessageError(callback, NError::MyFormatMessage(ERROR_ALREADY_EXISTS), outPath));
CFileInfo fi;
if (fi.Find(inPath))
{
if (state.TotalSize >= fi.Size)
state.TotalSize -= fi.Size;
}
return S_OK;
}
{
if (callback)
RINOK(callback->CompressOperation(fs2us(inPath)));
RINOK(state.MyCopyFile(inPath, outPath));
if (state.ErrorFileIndex >= 0)
{
if (state.ErrorMessage.IsEmpty())
state.ErrorMessage = GetLastErrorMessage();
FString errorName;
if (state.ErrorFileIndex == 0)
errorName = inPath;
else
errorName = outPath;
if (callback)
RINOK(SendMessageError(callback, state.ErrorMessage, errorName));
}
if (callback)
RINOK(callback->OperationResult(0));
}
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress)
{
CMyComPtr<IFolderArchiveUpdateCallback> callback;
if (progress)
{
RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&callback));
}
FString destPath = _pathPrefix + us2fs(newName);
const CAltStream &ss = Streams[index];
if (callback)
{
RINOK(callback->SetNumFiles(1));
RINOK(callback->SetTotal(ss.Size));
}
NFsFolder::CCopyStateIO state;
state.Progress = progress;
state.TotalSize = 0;
state.DeleteSrcFile = true;
return UpdateFile(state, _pathPrefix + us2fs(ss.Name), destPath, callback);
}
STDMETHODIMP CAltStreamsFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress *progress)
{
RINOK(progress->SetTotal(numItems));
for (UInt32 i = 0; i < numItems; i++)
{
const CAltStream &ss = Streams[indices[i]];
const FString fullPath = _pathPrefix + us2fs(ss.Name);
bool result = DeleteFileAlways(fullPath);
if (!result)
return Return_LastError_or_FAIL();
UInt64 completed = i;
RINOK(progress->SetCompleted(&completed));
}
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::SetProperty(UInt32 /* index */, PROPID /* propID */,
const PROPVARIANT * /* value */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
STDMETHODIMP CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
{
const CAltStream &ss = Streams[index];
*iconIndex = 0;
int iconIndexTemp;
if (GetRealIconIndex(_pathPrefix + us2fs(ss.Name),
0 // fi.Attrib
, iconIndexTemp) != 0)
{
*iconIndex = iconIndexTemp;
return S_OK;
}
return Return_LastError_or_FAIL();
}
/*
class CGetProp:
public IGetProp,
public CMyUnknownImp
{
public:
// const CArc *Arc;
// UInt32 IndexInArc;
UString Name; // relative path
UInt64 Size;
MY_UNKNOWN_IMP1(IGetProp)
INTERFACE_IGetProp(;)
};
STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value)
{
if (propID == kpidName)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop = Name;
prop.Detach(value);
return S_OK;
COM_TRY_END
}
if (propID == kpidSize)
{
NCOM::CPropVariant prop = Size;
prop.Detach(value);
return S_OK;
}
NCOM::CPropVariant prop;
prop.Detach(value);
return S_OK;
}
*/
static HRESULT CopyStream(
NFsFolder::CCopyStateIO &state,
const FString &srcPath,
const CFileInfo &srcFileInfo,
const CAltStream &srcAltStream,
const FString &destPathSpec,
IFolderOperationsExtractCallback *callback)
{
FString destPath = destPathSpec;
if (CompareFileNames(destPath, srcPath) == 0)
{
RINOK(SendMessageError(callback, "can not copy file onto itself", destPath));
return E_ABORT;
}
Int32 writeAskResult;
CMyComBSTR destPathResult;
RINOK(callback->AskWrite(
fs2us(srcPath),
BoolToInt(false),
&srcFileInfo.MTime, &srcAltStream.Size,
fs2us(destPath),
&destPathResult,
&writeAskResult));
if (IntToBool(writeAskResult))
{
RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
FString destPathNew = us2fs((LPCOLESTR)destPathResult);
RINOK(state.MyCopyFile(srcPath, destPathNew));
if (state.ErrorFileIndex >= 0)
{
if (state.ErrorMessage.IsEmpty())
state.ErrorMessage = GetLastErrorMessage();
FString errorName;
if (state.ErrorFileIndex == 0)
errorName = srcPath;
else
errorName = destPathNew;
RINOK(SendMessageError(callback, state.ErrorMessage, errorName));
return E_ABORT;
}
state.StartPos += state.CurrentSize;
}
else
{
if (state.TotalSize >= srcAltStream.Size)
{
state.TotalSize -= srcAltStream.Size;
RINOK(state.Progress->SetTotal(state.TotalSize));
}
}
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
const wchar_t *path, IFolderOperationsExtractCallback *callback)
{
if (numItems == 0)
return S_OK;
/*
CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
RINOK(callback->QueryInterface(IID_IFolderExtractToStreamCallback, (void **)&ExtractToStreamCallback));
if (ExtractToStreamCallback)
{
Int32 useStreams = 0;
if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK)
useStreams = 0;
if (useStreams == 0)
ExtractToStreamCallback.Release();
}
*/
UInt64 totalSize = 0;
{
UInt32 i;
for (i = 0; i < numItems; i++)
{
totalSize += Streams[indices[i]].Size;
}
RINOK(callback->SetTotal(totalSize));
RINOK(callback->SetNumFiles(numItems));
}
/*
if (ExtractToStreamCallback)
{
CGetProp *GetProp_Spec = new CGetProp;
CMyComPtr<IGetProp> GetProp= GetProp_Spec;
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 index = indices[i];
const CAltStream &ss = Streams[index];
GetProp_Spec->Name = ss.Name;
GetProp_Spec->Size = ss.Size;
CMyComPtr<ISequentialOutStream> outStream;
RINOK(ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, BoolToInt(false), &outStream,
NArchive::NExtract::NAskMode::kExtract, GetProp)); // isDir
FString srcPath;
GetFullPath(ss, srcPath);
RINOK(ExtractToStreamCallback->PrepareOperation7(NArchive::NExtract::NAskMode::kExtract));
RINOK(ExtractToStreamCallback->SetOperationResult7(NArchive::NExtract::NOperationResult::kOK, BoolToInt(false))); // _encrypted
// RINOK(CopyStream(state, srcPath, fi, ss, destPath2, callback, completedSize));
}
return S_OK;
}
*/
FString destPath = us2fs(path);
if (destPath.IsEmpty() /* && !ExtractToStreamCallback */)
return E_INVALIDARG;
bool isAltDest = NName::IsAltPathPrefix(destPath);;
bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
if (isDirectPath)
{
if (numItems > 1)
return E_INVALIDARG;
}
CFileInfo fi;
if (!fi.Find(_pathBaseFile))
return GetLastError();
NFsFolder::CCopyStateIO state;
state.Progress = callback;
state.DeleteSrcFile = IntToBool(moveMode);
state.TotalSize = totalSize;
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 index = indices[i];
const CAltStream &ss = Streams[index];
FString destPath2 = destPath;
if (!isDirectPath)
destPath2 += us2fs(Get_Correct_FsFile_Name(ss.Name));
FString srcPath;
GetFullPath(ss, srcPath);
RINOK(CopyStream(state, srcPath, fi, ss, destPath2, callback));
}
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
{
/*
if (numItems == 0)
return S_OK;
CMyComPtr<IFolderArchiveUpdateCallback> callback;
if (progress)
{
RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&callback));
}
if (CompareFileNames(fromFolderPath, fs2us(_pathPrefix)) == 0)
{
RINOK(SendMessageError(callback, "can not copy file onto itself", _pathPrefix));
return E_ABORT;
}
if (callback)
RINOK(callback->SetNumFiles(numItems));
UInt64 totalSize = 0;
UInt32 i;
FString path;
for (i = 0; i < numItems; i++)
{
path = us2fs(fromFolderPath);
path += us2fs(itemsPaths[i]);
CFileInfo fi;
if (!fi.Find(path))
return ::GetLastError();
if (fi.IsDir())
return E_NOTIMPL;
totalSize += fi.Size;
}
RINOK(progress->SetTotal(totalSize));
// UInt64 completedSize = 0;
NFsFolder::CCopyStateIO state;
state.Progress = progress;
state.DeleteSrcFile = IntToBool(moveMode);
state.TotalSize = totalSize;
// we need to clear READ-ONLY of parent before creating alt stream
{
DWORD attrib = GetFileAttrib(_pathBaseFile);
if (attrib != INVALID_FILE_ATTRIBUTES
&& (attrib & FILE_ATTRIBUTE_READONLY) != 0)
{
if (!SetFileAttrib(_pathBaseFile, attrib & ~FILE_ATTRIBUTE_READONLY))
{
if (callback)
{
RINOK(SendMessageError(callback, GetLastErrorMessage(), _pathBaseFile));
return S_OK;
}
return Return_LastError_or_FAIL();
}
}
}
for (i = 0; i < numItems; i++)
{
path = us2fs(fromFolderPath);
path += us2fs(itemsPaths[i]);
FString destPath = _pathPrefix + us2fs(itemsPaths[i]);
RINOK(UpdateFile(state, path, destPath, callback));
}
return S_OK;
*/
return E_NOTIMPL;
}
STDMETHODIMP CAltStreamsFolder::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
}

View File

@@ -0,0 +1,100 @@
// AltStreamsFolder.h
#ifndef __ALT_STREAMS_FOLDER_H
#define __ALT_STREAMS_FOLDER_H
#include "../../../Common/MyCom.h"
#include "../../../Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "IFolder.h"
namespace NAltStreamsFolder {
class CAltStreamsFolder;
struct CAltStream
{
UInt64 Size;
UInt64 PackSize;
bool PackSize_Defined;
UString Name;
};
class CAltStreamsFolder:
public IFolderFolder,
public IFolderCompare,
#ifdef USE_UNICODE_FSTRING
public IFolderGetItemName,
#endif
public IFolderWasChanged,
public IFolderOperations,
// public IFolderOperationsDeleteToRecycleBin,
public IFolderClone,
public IFolderGetSystemIconIndex,
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
MY_QUERYINTERFACE_ENTRY(IFolderCompare)
#ifdef USE_UNICODE_FSTRING
MY_QUERYINTERFACE_ENTRY(IFolderGetItemName)
#endif
MY_QUERYINTERFACE_ENTRY(IFolderWasChanged)
// MY_QUERYINTERFACE_ENTRY(IFolderOperationsDeleteToRecycleBin)
MY_QUERYINTERFACE_ENTRY(IFolderOperations)
MY_QUERYINTERFACE_ENTRY(IFolderClone)
MY_QUERYINTERFACE_ENTRY(IFolderGetSystemIconIndex)
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_FolderFolder(;)
INTERFACE_FolderOperations(;)
STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
#ifdef USE_UNICODE_FSTRING
INTERFACE_IFolderGetItemName(;)
#endif
STDMETHOD(WasChanged)(Int32 *wasChanged);
STDMETHOD(Clone)(IFolderFolder **resultFolder);
STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
private:
FString _pathBaseFile; // folder
FString _pathPrefix; // folder:
CObjectVector<CAltStream> Streams;
// CMyComPtr<IFolderFolder> _parentFolder;
NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;
HRESULT GetItemFullSize(unsigned index, UInt64 &size, IProgress *progress);
void GetAbsPath(const wchar_t *name, FString &absPath);
public:
// path must be with ':' at tail
HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */);
CAltStreamsFolder() {}
void GetFullPath(const CAltStream &item, FString &path) const
{
path = _pathPrefix;
path += us2fs(item.Name);
}
void Clear()
{
Streams.Clear();
}
};
}
#endif

View File

@@ -140,8 +140,8 @@ HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UStr
}
static void CreateToolbar(HWND parent,
NWindows::NControl::CImageList &imageList,
NWindows::NControl::CToolBar &toolBar,
NControl::CImageList &imageList,
NControl::CToolBar &toolBar,
bool largeButtons)
{
toolBar.Attach(::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, 0
@@ -364,7 +364,8 @@ void CApp::Save()
if (panel._parentFolders.IsEmpty())
path = panel._currentFolderPrefix;
else
path = GetFolderPath(panel._parentFolders[0].ParentFolder);
path = panel._parentFolders[0].ParentFolderPath;
// GetFolderPath(panel._parentFolders[0].ParentFolder);
SavePanelPath(i, path);
listMode.Panels[i] = panel.GetListViewMode();
SaveFlatView(i, panel._flatModeForArc);
@@ -380,9 +381,12 @@ void CApp::Release()
Panels[i].Release();
}
// reduces path to part that exists on disk
// reduces path to part that exists on disk (or root prefix of path)
// output path is normalized (with WCHAR_PATH_SEPARATOR)
static void ReducePathToRealFileSystemPath(UString &path)
{
unsigned prefixSize = GetRootPrefixSize(path);
while (!path.IsEmpty())
{
if (NFind::DoesDirExist(us2fs(path)))
@@ -390,63 +394,59 @@ static void ReducePathToRealFileSystemPath(UString &path)
NName::NormalizeDirPathPrefix(path);
break;
}
int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR);
int pos = path.ReverseFind_PathSepar();
if (pos < 0)
{
path.Empty();
break;
}
path.DeleteFrom(pos + 1);
if (path.Len() == 3 && path[1] == L':')
if ((unsigned)pos + 1 == prefixSize)
break;
if (path.Len() > 2 && path[0] == '\\' && path[1] == '\\')
{
int nextPos = path.Find(WCHAR_PATH_SEPARATOR, 2); // pos after \\COMPNAME
if (nextPos > 0 && path.Find(WCHAR_PATH_SEPARATOR, nextPos + 1) == pos)
break;
}
path.DeleteFrom(pos);
}
}
// return true for dir\, if dir exist
// returns: true, if such dir exists or is root
/*
static bool CheckFolderPath(const UString &path)
{
UString pathReduced = path;
ReducePathToRealFileSystemPath(pathReduced);
return (pathReduced == path);
}
*/
extern UString ConvertSizeToString(UInt64 value);
static UString AddSizeValue(UInt64 size)
static void AddSizeValue(UString &s, UInt64 size)
{
return MyFormatNew(IDS_FILE_SIZE, ConvertSizeToString(size));
s += MyFormatNew(IDS_FILE_SIZE, ConvertSizeToString(size));
}
static void AddValuePair1(UString &s, UINT resourceID, UInt64 size)
{
s += LangString(resourceID);
AddLangString(s, resourceID);
s += L": ";
s += AddSizeValue(size);
s += L'\n';
AddSizeValue(s, size);
s.Add_LF();
}
void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size)
{
if (num == 0)
return;
s += LangString(resourceID);
AddLangString(s, resourceID);
s += L": ";
s += ConvertSizeToString(num);
if (size != (UInt64)(Int64)-1)
{
s += L" ( ";
s += AddSizeValue(size);
AddSizeValue(s, size);
s += L" )";
}
s += L'\n';
s.Add_LF();
}
static void AddPropValueToSum(IFolderFolder *folder, int index, PROPID propID, UInt64 &sum)
@@ -490,7 +490,7 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices)
if (numDefined == 2)
AddValuePair1(info, IDS_PROP_SIZE, filesSize + foldersSize);
info += L"\n";
info.Add_LF();
info += _currentFolderPrefix;
for (i = 0; i < indices.Size() && (int)i < (int)kCopyDialog_NumInfoLines - 6; i++)
@@ -499,7 +499,7 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices)
int index = indices[i];
info += GetItemRelPath(index);
if (IsItem_Folder(index))
info += WCHAR_PATH_SEPARATOR;
info.Add_PathSepar();
}
if (i != indices.Size())
info += L"\n ...";
@@ -508,6 +508,20 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices)
bool IsCorrectFsName(const UString &name);
/* Returns true, if path is path that can be used as path for File System functions
*/
/*
static bool IsFsPath(const FString &path)
{
if (!IsAbsolutePath(path))
return false;
unsigned prefixSize = GetRootPrefixSize(path);
}
*/
void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
{
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
@@ -517,7 +531,12 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
CPanel::CDisableTimerProcessing disableTimerProcessing1(destPanel);
CPanel::CDisableTimerProcessing disableTimerProcessing2(srcPanel);
if (!srcPanel.DoesItSupportOperations())
if (move)
{
if (!srcPanel.CheckBeforeUpdate(IDS_MOVE))
return;
}
else if (!srcPanel.DoesItSupportOperations())
{
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
@@ -544,13 +563,15 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
srcPanel.GetOperatedIndicesSmart(indices);
if (indices.Size() == 0)
return;
destPath = destPanel._currentFolderPrefix;
destPath = destPanel.GetFsPath();
if (NumPanels == 1)
ReducePathToRealFileSystemPath(destPath);
}
}
UStringVector copyFolders;
ReadCopyHistory(copyFolders);
{
CCopyDialog copyDialog;
@@ -583,10 +604,10 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
if (IsAbsolutePath(destPath))
destPath.Empty();
else
destPath = srcPanel._currentFolderPrefix;
destPath = srcPanel.GetFsPath();
destPath += correctName;
#ifndef UNDER_CE
#if defined(_WIN32) && !defined(UNDER_CE)
if (destPath.Len() > 0 && destPath[0] == '\\')
if (destPath.Len() == 1 || destPath[1] != '\\')
{
@@ -595,59 +616,112 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
}
#endif
if (indices.Size() > 1 ||
(!destPath.IsEmpty() && destPath.Back() == WCHAR_PATH_SEPARATOR) ||
NFind::DoesDirExist(us2fs(destPath)) ||
srcPanel.IsArcFolder())
bool possibleToUseDestPanel = false;
if (CompareFileNames(destPath, destPanel.GetFsPath()) == 0)
{
CreateComplexDir(us2fs(destPath));
NName::NormalizeDirPathPrefix(destPath);
if (!CheckFolderPath(destPath))
if (NumPanels == 1 || CompareFileNames(destPath, srcPanel.GetFsPath()) == 0)
{
if (NumPanels < 2 || destPath != destPanel._currentFolderPrefix || !destPanel.DoesItSupportOperations())
{
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
}
useDestPanel = true;
srcPanel.MessageBoxMyError(L"Can not copy files onto itself");
return;
}
if (destPanel.DoesItSupportOperations())
possibleToUseDestPanel = true;
}
bool destIsFsPath = false;
if (possibleToUseDestPanel)
{
if (destPanel.IsFSFolder() || destPanel.IsAltStreamsFolder())
destIsFsPath = true;
else if (destPanel.IsFSDrivesFolder() || destPanel.IsRootFolder())
{
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
}
}
else
{
if (!IsCorrectFsName(destPath))
if (IsAltPathPrefix(us2fs(destPath)))
{
srcPanel.MessageBoxError(E_INVALIDARG);
// we allow alt streams dest only to alt stream folder in second panel
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
}
int pos = destPath.ReverseFind(WCHAR_PATH_SEPARATOR);
if (pos >= 0)
{
UString prefix = destPath.Left(pos + 1);
CreateComplexDir(us2fs(prefix));
if (!CheckFolderPath(prefix))
/*
FString basePath = us2fs(destPath);
basePath.DeleteBack();
if (!DoesFileOrDirExist(basePath))
{
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
srcPanel.MessageBoxError2Lines(basePath, ERROR_FILE_NOT_FOUND); // GetLastError()
return;
}
destIsFsPath = true;
*/
}
else
{
if (indices.Size() == 1 &&
!destPath.IsEmpty() && destPath.Back() != WCHAR_PATH_SEPARATOR)
{
int pos = destPath.ReverseFind_PathSepar();
if (pos < 0)
{
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
}
{
/*
#ifdef _WIN32
UString name = destPath.Ptr(pos + 1);
if (name.Find(L':') >= 0)
{
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
}
#endif
*/
UString prefix = destPath.Left(pos + 1);
if (!CreateComplexDir(us2fs(prefix)))
{
srcPanel.MessageBoxError2Lines(prefix, GetLastError());
return;
}
}
// bool isFolder = srcPanael.IsItem_Folder(indices[0]);
}
else
{
NName::NormalizeDirPathPrefix(destPath);
if (!CreateComplexDir(us2fs(destPath)))
{
srcPanel.MessageBoxError2Lines(destPath, GetLastError());
return;
}
}
destIsFsPath = true;
}
}
if (!destIsFsPath)
useDestPanel = true;
AddUniqueStringToHeadOfList(copyFolders, destPath);
while (copyFolders.Size() > 20)
copyFolders.DeleteBack();
SaveCopyHistory(copyFolders);
}
/*
if (destPath == destPanel._currentFolderPrefix)
{
if (destPanel.GetFolderTypeID() == L"PhysDrive")
useDestPanel = true;
}
*/
bool useSrcPanel = !useDestPanel || !srcPanel.Is_IO_FS_Folder();
bool useSrcPanel = (!useDestPanel || !srcPanel.IsFsOrDrivesFolder() || destPanel.IsFSFolder());
bool useTemp = useSrcPanel && useDestPanel;
if (useTemp && NumPanels == 1)
{
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
}
CTempDir tempDirectory;
FString tempDirPrefix;
if (useTemp)
@@ -666,6 +740,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
CPanel::CDisableNotify disableNotify2(srcPanel);
HRESULT result = S_OK;
if (useSrcPanel)
{
CCopyToOptions options;
@@ -685,12 +760,13 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
if (useTemp)
folderPrefix = fs2us(tempDirPrefix);
else
folderPrefix = srcPanel._currentFolderPrefix;
folderPrefix = srcPanel.GetFsPath();
filePaths.ClearAndReserve(indices.Size());
FOR_VECTOR (i, indices)
filePaths.AddInReserved(srcPanel.GetItemRelPath(indices[i]));
filePaths.AddInReserved(srcPanel.GetItemRelPath2(indices[i]));
result = destPanel.CopyFrom(move, folderPrefix, filePaths, true, 0);
}
if (result != S_OK)
{
// disableNotify1.Restore();
@@ -705,15 +781,18 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
}
RefreshTitleAlways();
if (copyToSame || move)
{
srcPanel.RefreshListCtrl(srcSelState);
}
if (!copyToSame)
{
destPanel.RefreshListCtrl(destSelState);
srcPanel.KillSelection();
}
disableNotify1.Restore();
disableNotify2.Restore();
srcPanel.SetFocusToList();
@@ -831,7 +910,7 @@ void CApp::RefreshTitle(int panelIndex, bool always)
void AddUniqueStringToHead(UStringVector &list, const UString &s)
{
for (unsigned i = 0; i < list.Size();)
if (s.IsEqualToNoCase(list[i]))
if (s.IsEqualTo_NoCase(list[i]))
list.Delete(i);
else
i++;
@@ -848,7 +927,7 @@ void CFolderHistory::Normalize()
void CFolderHistory::AddString(const UString &s)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
NSynchronization::CCriticalSectionLock lock(_criticalSection);
AddUniqueStringToHead(Strings, s);
Normalize();
}

View File

@@ -195,6 +195,7 @@ public:
void CopyTo() { OnCopy(false, false, GetFocusedPanelIndex()); }
void MoveTo() { OnCopy(true, false, GetFocusedPanelIndex()); }
void Delete(bool toRecycleBin) { GetFocusedPanel().DeleteItems(toRecycleBin); }
HRESULT CalculateCrc2(const UString &methodName);
void CalculateCrc(const UString &methodName);
void DiffFiles();
void Split();
@@ -204,6 +205,7 @@ public:
#ifndef UNDER_CE
void Link();
void OpenAltStreams() { GetFocusedPanel().OpenAltStreams(); }
#endif
void CreateFolder() { GetFocusedPanel().CreateFolder(); }

View File

@@ -77,7 +77,7 @@ static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *nam
UString s = HResultToMessage(errorCode);
if (name)
{
s += L'\n';
s.Add_LF();
s += name;
}
MessageBox_Error_Global(wnd, s);
@@ -209,7 +209,7 @@ bool CBrowseDialog::OnInit()
FOR_VECTOR (i, Filters)
{
if (i != 0)
s += L' ';
s.Add_Space();
s += Filters[i];
}
}
@@ -256,14 +256,16 @@ bool CBrowseDialog::OnInit()
_topDirPrefix.Empty();
{
int rootSize = GetRootPrefixSize(FilePath);
#if defined(_WIN32) && !defined(UNDER_CE)
// We can go up from root folder to drives list
if (NName::IsDrivePath(FilePath))
if (IsDrivePath(FilePath))
rootSize = 0;
else if (IsSuperPath(FilePath))
{
if (NName::IsDrivePath(&FilePath[kSuperPathPrefixSize]))
if (IsDrivePath(FilePath.Ptr(kSuperPathPrefixSize)))
rootSize = kSuperPathPrefixSize;
}
#endif
_topDirPrefix.SetFrom(FilePath, rootSize);
}
@@ -466,7 +468,7 @@ bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, US
return false;
if (s.Back() == WCHAR_PATH_SEPARATOR)
return false;
int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);
int pos = s.ReverseFind_PathSepar();
parentPrefix.SetFrom(s, pos + 1);
name = s.Ptr(pos + 1);
return true;
@@ -856,7 +858,7 @@ bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path,
return false;
{
UString s = errorMessage;
s += L"\n";
s.Add_LF();
s += path;
MessageBox_Error_Global(owner, s);
}
@@ -904,27 +906,32 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result
result.Empty();
UString path = path2;
path.Replace('/', WCHAR_PATH_SEPARATOR);
path.Replace(L'/', WCHAR_PATH_SEPARATOR);
unsigned start = 0;
UString base;
if (NName::IsAbsolutePath(path))
if (IsAbsolutePath(path))
{
#if defined(_WIN32) && !defined(UNDER_CE)
if (IsSuperOrDevicePath(path))
{
result = path;
return true;
}
#endif
int pos = GetRootPrefixSize(path);
if (pos > 0)
start = pos;
}
else
{
#if defined(_WIN32) && !defined(UNDER_CE)
if (IsSuperOrDevicePath(relBase))
{
result = path;
return true;
}
#endif
base = relBase;
}
@@ -954,6 +961,7 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result
result += path.Left(start);
bool checkExist = true;
UString cur;
for (;;)
{
if (start == path.Len())
@@ -979,7 +987,7 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result
result += cur;
if (slashPos < 0)
break;
result += WCHAR_PATH_SEPARATOR;
result.Add_PathSepar();
start = slashPos + 1;
}

View File

@@ -9,7 +9,7 @@ bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultP
bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath);
/* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file)
But it doesn't change "bad" name in any of the following caes:
But it doesn't change "bad" name in any of the following cases:
- path is Super Path (with \\?\ prefix)
- path is relative and relBase is Super Path
- there is file or dir in filesystem with specified "bad" name */

View File

@@ -1,7 +1,7 @@
#include "EditPageRes.h"
#include "../../GuiCommon.rc"
#define xc 200
#define xc 240
#define yc 80
IDD_EDIT MY_PAGE

View File

@@ -22,6 +22,7 @@
#endif
#include "../GUI/ExtractRes.h"
#include "resourceGui.h"
#include "ExtractCallback.h"
#include "FormatUtils.h"
@@ -30,6 +31,7 @@
#ifndef _NO_CRYPTO
#include "PasswordDialog.h"
#endif
#include "PropertyName.h"
using namespace NWindows;
using namespace NFile;
@@ -39,6 +41,10 @@ CExtractCallbackImp::~CExtractCallbackImp() {}
void CExtractCallbackImp::Init()
{
_lang_Extracting = LangString(IDS_PROGRESS_EXTRACTING);
_lang_Testing = LangString(IDS_PROGRESS_TESTING);
_lang_Skipping = LangString(IDS_PROGRESS_SKIPPING);
NumArchiveErrors = 0;
ThereAreMessageErrors = false;
#ifndef _SFX
@@ -97,6 +103,11 @@ HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, co
return ProgressDialog->Sync.CheckStop();
}
HRESULT CExtractCallbackImp::Open_Finished()
{
return ProgressDialog->Sync.CheckStop();
}
#ifndef _NO_CRYPTO
HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password)
@@ -104,6 +115,7 @@ HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password)
return CryptoGetTextPassword(password);
}
/*
HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)
{
passwordIsDefined = PasswordIsDefined;
@@ -116,10 +128,11 @@ bool CExtractCallbackImp::Open_WasPasswordAsked()
return PasswordWasAsked;
}
void CExtractCallbackImp::Open_ClearPasswordWasAskedFlag()
void CExtractCallbackImp::Open_Clear_PasswordWasAsked_Flag()
{
PasswordWasAsked = false;
}
*/
#endif
@@ -179,10 +192,21 @@ STDMETHODIMP CExtractCallbackImp::AskOverwrite(
}
STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, bool isFolder, Int32 /* askExtractMode */, const UInt64 * /* position */)
STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 * /* position */)
{
_isFolder = isFolder;
return SetCurrentFilePath2(name);
_isFolder = IntToBool(isFolder);
_currentFilePath = name;
const UString *msg = &_lang_Empty;
switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract: msg = &_lang_Extracting; break;
case NArchive::NExtract::NAskMode::kTest: msg = &_lang_Testing; break;
case NArchive::NExtract::NAskMode::kSkip: msg = &_lang_Skipping; break;
// default: s = "Unknown operation";
}
return ProgressDialog->Sync.Set_Status2(*msg, name, IntToBool(isFolder));
}
STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *s)
@@ -208,7 +232,98 @@ STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *s)
#endif
STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, bool encrypted)
void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s)
{
s.Empty();
if (opRes == NArchive::NExtract::NOperationResult::kOK)
return;
UINT messageID = 0;
UINT id = 0;
switch (opRes)
{
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD;
id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD;
break;
case NArchive::NExtract::NOperationResult::kDataError:
messageID = encrypted ?
IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED:
IDS_EXTRACT_MESSAGE_DATA_ERROR;
id = IDS_EXTRACT_MSG_DATA_ERROR;
break;
case NArchive::NExtract::NOperationResult::kCRCError:
messageID = encrypted ?
IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED:
IDS_EXTRACT_MESSAGE_CRC_ERROR;
id = IDS_EXTRACT_MSG_CRC_ERROR;
break;
case NArchive::NExtract::NOperationResult::kUnavailable:
id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA;
break;
case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
id = IDS_EXTRACT_MSG_UEXPECTED_END;
break;
case NArchive::NExtract::NOperationResult::kDataAfterEnd:
id = IDS_EXTRACT_MSG_DATA_AFTER_END;
break;
case NArchive::NExtract::NOperationResult::kIsNotArc:
id = IDS_EXTRACT_MSG_IS_NOT_ARC;
break;
case NArchive::NExtract::NOperationResult::kHeadersError:
id = IDS_EXTRACT_MSG_HEADERS_ERROR;
break;
case NArchive::NExtract::NOperationResult::kWrongPassword:
id = IDS_EXTRACT_MSG_WRONG_PSW_CLAIM;
break;
/*
default:
messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR;
break;
*/
}
UString msg;
UString msgOld;
#ifndef _SFX
if (id != 0)
LangString_OnlyFromLangFile(id, msg);
if (messageID != 0 && msg.IsEmpty())
LangString_OnlyFromLangFile(messageID, msgOld);
#endif
if (msg.IsEmpty() && !msgOld.IsEmpty())
s = MyFormatNew(msgOld, fileName);
else
{
if (msg.IsEmpty() && id != 0)
LangString(id, msg);
if (!msg.IsEmpty())
s += msg;
else
{
char temp[16];
ConvertUInt32ToString(opRes, temp);
s.AddAscii("Error #");
s.AddAscii(temp);
}
if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword)
{
// s.AddAscii(" : ");
// AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED);
s.AddAscii(" : ");
AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);
}
s.AddAscii(" : ");
s += fileName;
}
}
STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypted)
{
switch (opRes)
{
@@ -216,93 +331,9 @@ STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, bool encrypted
break;
default:
{
UINT messageID = 0;
UINT id = 0;
switch (opRes)
{
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD;
id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD;
break;
case NArchive::NExtract::NOperationResult::kDataError:
messageID = encrypted ?
IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED:
IDS_EXTRACT_MESSAGE_DATA_ERROR;
id = IDS_EXTRACT_MSG_DATA_ERROR;
break;
case NArchive::NExtract::NOperationResult::kCRCError:
messageID = encrypted ?
IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED:
IDS_EXTRACT_MESSAGE_CRC_ERROR;
id = IDS_EXTRACT_MSG_CRC_ERROR;
break;
case NArchive::NExtract::NOperationResult::kUnavailable:
id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA;
break;
case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
id = IDS_EXTRACT_MSG_UEXPECTED_END;
break;
case NArchive::NExtract::NOperationResult::kDataAfterEnd:
id = IDS_EXTRACT_MSG_DATA_AFTER_END;
break;
case NArchive::NExtract::NOperationResult::kIsNotArc:
id = IDS_EXTRACT_MSG_IS_NOT_ARC;
break;
case NArchive::NExtract::NOperationResult::kHeadersError:
id = IDS_EXTRACT_MSG_HEADERS_ERROR;
break;
/*
default:
messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR;
break;
*/
}
if (_needWriteArchivePath)
{
if (!_currentArchivePath.IsEmpty())
AddError_Message(_currentArchivePath);
_needWriteArchivePath = false;
}
UString msg;
UString msgOld;
#ifndef _SFX
if (id != 0)
LangString_OnlyFromLangFile(id, msg);
if (messageID != 0 && msg.IsEmpty())
LangString_OnlyFromLangFile(messageID, msgOld);
#endif
UString s;
if (msg.IsEmpty() && !msgOld.IsEmpty())
s = MyFormatNew(msgOld, _currentFilePath);
else
{
if (msg.IsEmpty())
LangString(id, msg);
if (!msg.IsEmpty())
s += msg;
else
{
wchar_t temp[16];
ConvertUInt32ToString(opRes, temp);
s += L"Error #";
s += temp;
}
if (encrypted)
{
// s += L" : ";
// s += LangString(IDS_EXTRACT_MSG_ENCRYPTED);
s += L" : ";
s += LangString(IDS_EXTRACT_MSG_WRONG_PSW);
}
s += L" : ";
s += _currentFilePath;
}
SetExtractErrorMessage(opRes, encrypted, _currentFilePath, s);
Add_ArchiveName_Error();
AddError_Message(s);
}
}
@@ -318,10 +349,22 @@ STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, bool encrypted
return S_OK;
}
STDMETHODIMP CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)
{
if (opRes != NArchive::NExtract::NOperationResult::kOK)
{
UString s;
SetExtractErrorMessage(opRes, encrypted, name, s);
Add_ArchiveName_Error();
AddError_Message(s);
}
return S_OK;
}
////////////////////////////////////////
// IExtractCallbackUI
HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name)
HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name, bool /* testMode */)
{
#ifndef _SFX
RINOK(ProgressDialog->Sync.CheckStop());
@@ -357,27 +400,6 @@ HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path)
UString HResultToMessage(HRESULT errorCode);
HRESULT CExtractCallbackImp::OpenResult(const wchar_t *name, HRESULT result, bool encrypted)
{
if (result != S_OK)
{
UString s;
if (result == S_FALSE)
s = MyFormatNew(encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE, name);
else
{
s = name;
s += L": ";
s += HResultToMessage(result);
}
MessageError(s);
NumArchiveErrors++;
}
_currentArchivePath = name;
_needWriteArchivePath = true;
return S_OK;
}
static const UInt32 k_ErrorFlagsIds[] =
{
IDS_EXTRACT_MSG_IS_NOT_ARC,
@@ -393,9 +415,16 @@ static const UInt32 k_ErrorFlagsIds[] =
IDS_EXTRACT_MSG_CRC_ERROR
};
static void AddNewLineString(UString &s, const UString &m)
{
s += m;
s.Add_LF();
}
UString GetOpenArcErrorMessage(UInt32 errorFlags)
{
UString s;
for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsIds); i++)
{
UInt32 f = ((UInt32)1 << i);
@@ -407,14 +436,15 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags)
continue;
if (f == kpv_ErrorFlags_EncryptedHeadersError)
{
m += L" : ";
m += LangString(IDS_EXTRACT_MSG_WRONG_PSW);
m.AddAscii(" : ");
AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);
}
if (!s.IsEmpty())
s += L'\n';
s.Add_LF();
s += m;
errorFlags &= ~f;
}
if (errorFlags != 0)
{
char sz[16];
@@ -422,74 +452,151 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags)
sz[1] = 'x';
ConvertUInt32ToHex(errorFlags, sz + 2);
if (!s.IsEmpty())
s += L'\n';
s += GetUnicodeString(AString(sz));
s.Add_LF();
s.AddAscii(sz);
}
return s;
}
HRESULT CExtractCallbackImp::SetError(int level, const wchar_t *name,
UInt32 errorFlags, const wchar_t *errors,
UInt32 warningFlags, const wchar_t *warnings)
static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er)
{
NumArchiveErrors++;
UInt32 errorFlags = er.GetErrorFlags();
UInt32 warningFlags = er.GetWarningFlags();
if (errorFlags != 0)
AddNewLineString(s, GetOpenArcErrorMessage(errorFlags));
if (!er.ErrorMessage.IsEmpty())
AddNewLineString(s, er.ErrorMessage);
if (warningFlags != 0)
{
s += GetNameOfProperty(kpidWarningFlags, L"Warnings");
s.AddAscii(":");
s.Add_LF();
AddNewLineString(s, GetOpenArcErrorMessage(warningFlags));
}
if (!er.WarningMessage.IsEmpty())
{
s += GetNameOfProperty(kpidWarning, L"Warning");
s.AddAscii(": ");
s += er.WarningMessage;
s.Add_LF();
}
}
static UString GetBracedType(const wchar_t *type)
{
UString s = L'[';
s += type;
s += L']';
return s;
}
void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)
{
FOR_VECTOR (level, arcLink.Arcs)
{
const CArc &arc = arcLink.Arcs[level];
const CArcErrorInfo &er = arc.ErrorInfo;
if (!er.IsThereErrorOrWarning() && er.ErrorFormatIndex < 0)
continue;
if (s.IsEmpty())
{
s += name;
s.Add_LF();
}
if (level != 0)
{
AddNewLineString(s, arc.Path);
}
ErrorInfo_Print(s, er);
if (er.ErrorFormatIndex >= 0)
{
AddNewLineString(s, GetNameOfProperty(kpidWarning, L"Warning"));
if (arc.FormatIndex == er.ErrorFormatIndex)
{
AddNewLineString(s, LangString(IDS_IS_OPEN_WITH_OFFSET));
}
else
{
AddNewLineString(s, MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(er.ErrorFormatIndex))));
AddNewLineString(s, MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(arc.FormatIndex))));
}
}
}
if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result != S_OK)
{
s += name;
s.Add_LF();
if (!arcLink.Arcs.IsEmpty())
AddNewLineString(s, arcLink.NonOpen_ArcPath);
if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result == S_FALSE)
{
UINT id = IDS_CANT_OPEN_ARCHIVE;
UString param;
if (arcLink.PasswordWasAsked)
id = IDS_CANT_OPEN_ENCRYPTED_ARCHIVE;
else if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
{
id = IDS_CANT_OPEN_AS_TYPE;
param = GetBracedType(codecs->GetFormatNamePtr(arcLink.NonOpen_ErrorInfo.ErrorFormatIndex));
}
UString s2 = MyFormatNew(id, param);
s2.Replace(L" ''", L"");
s2.Replace(L"''", L"");
s += s2;
}
else
s += HResultToMessage(result);
s.Add_LF();
ErrorInfo_Print(s, arcLink.NonOpen_ErrorInfo);
}
if (!s.IsEmpty() && s.Back() == '\n')
s.DeleteBack();
}
HRESULT CExtractCallbackImp::OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)
{
_currentArchivePath = name;
_needWriteArchivePath = true;
UString s;
OpenResult_GUI(s, codecs, arcLink, name, result);
if (!s.IsEmpty())
{
NumArchiveErrors++;
AddError_Message(s);
_needWriteArchivePath = false;
}
return S_OK;
}
HRESULT CExtractCallbackImp::ThereAreNoFiles()
{
return S_OK;
}
void CExtractCallbackImp::Add_ArchiveName_Error()
{
if (_needWriteArchivePath)
{
if (!_currentArchivePath.IsEmpty())
AddError_Message(_currentArchivePath);
_needWriteArchivePath = false;
}
if (level != 0)
{
UString s;
s += name;
s += L": ";
MessageError(s);
}
if (errorFlags != 0)
MessageError(GetOpenArcErrorMessage(errorFlags));
if (errors && wcslen(errors) != 0)
MessageError(errors);
if (warningFlags != 0)
MessageError((UString)L"Warnings: " + GetOpenArcErrorMessage(warningFlags));
if (warnings && wcslen(warnings) != 0)
MessageError((UString)L"Warnings: " + warnings);
return S_OK;
}
HRESULT CExtractCallbackImp::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType)
{
UString s = L"Warning:\n";
s += name;
s += L"\n";
if (wcscmp(okType, errorType) == 0)
{
s += L"The archive is open with offset";
}
else
{
s += L"Can not open the file as [";
s += errorType;
s += L"] archive\n";
s += L"The file is open as [";
s += okType;
s += L"] archive";
}
MessageError(s);
NumArchiveErrors++;
return S_OK;
}
HRESULT CExtractCallbackImp::ThereAreNoFiles()
{
return S_OK;
}
HRESULT CExtractCallbackImp::ExtractResult(HRESULT result)
@@ -499,7 +606,10 @@ HRESULT CExtractCallbackImp::ExtractResult(HRESULT result)
NumArchiveErrors++;
if (result == E_ABORT || result == ERROR_DISK_FULL)
return result;
MessageError(_currentFilePath);
Add_ArchiveName_Error();
if (!_currentFilePath.IsEmpty())
MessageError(_currentFilePath);
MessageError(NError::MyFormatMessage(result));
return S_OK;
}
@@ -564,7 +674,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
{
if (!destFileInfo.IsDir())
{
RINOK(MessageError("can not replace file with folder with same name: ", destPathSys));
RINOK(MessageError("can not replace file with folder with same name", destPathSys));
return E_ABORT;
}
*writeAnswer = BoolToInt(false);
@@ -573,8 +683,9 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
if (destFileInfo.IsDir())
{
RINOK(MessageError("can not replace folder with file with same name: ", destPathSys));
return E_FAIL;
RINOK(MessageError("can not replace folder with file with same name", destPathSys));
*writeAnswer = BoolToInt(false);
return S_OK;
}
switch (OverwriteMode)
@@ -583,13 +694,9 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
return S_OK;
case NExtract::NOverwriteMode::kAsk:
{
Int32 overwiteResult;
Int32 overwriteResult;
UString destPathSpec = destPath;
int slashPos = destPathSpec.ReverseFind(L'/');
#ifdef _WIN32
int slash1Pos = destPathSpec.ReverseFind(L'\\');
slashPos = MyMax(slashPos, slash1Pos);
#endif
int slashPos = destPathSpec.ReverseFind_PathSepar();
destPathSpec.DeleteFrom(slashPos + 1);
destPathSpec += fs2us(destFileInfo.Name);
@@ -598,9 +705,9 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
&destFileInfo.MTime, &destFileInfo.Size,
srcPath,
srcTime, srcSize,
&overwiteResult));
&overwriteResult));
switch (overwiteResult)
switch (overwriteResult)
{
case NOverwriteAnswer::kCancel: return E_ABORT;
case NOverwriteAnswer::kNo: return S_OK;
@@ -618,7 +725,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
{
if (!AutoRenamePath(destPathSys))
{
RINOK(MessageError("can not create name for file: ", destPathSys));
RINOK(MessageError("can not create name for file", destPathSys));
return E_ABORT;
}
destPathResultTemp = fs2us(destPathSys);
@@ -626,7 +733,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
else
if (!NDir::DeleteFileAlways(destPathSys))
{
RINOK(MessageError("can not delete output file: ", destPathSys));
RINOK(MessageError("can not delete output file", destPathSys));
return E_ABORT;
}
}
@@ -783,7 +890,7 @@ STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode)
COM_TRY_END
}
STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, bool encrypted)
STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, Int32 encrypted)
{
COM_TRY_BEGIN
if (VirtFileSystem && _newVirtFileWasAdded)
@@ -865,7 +972,7 @@ HRESULT CVirtFileSystem::FlushToDisk(bool closeLast)
while (_numFlushed < Files.Size())
{
const CVirtFile &file = Files[_numFlushed];
const FString path = DirPrefix + us2fs(GetCorrectFsPath(file.Name));
const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name));
if (!_fileIsOpen)
{
if (!_outFileStreamSpec->Create(path, false))

View File

@@ -36,8 +36,7 @@ class CGrowBuf
Byte *_items;
size_t _size;
CGrowBuf(const CGrowBuf &buffer);
void operator=(const CGrowBuf &buffer);
CLASS_NO_COPY(CGrowBuf);
public:
bool ReAlloc_KeepData(size_t newSize, size_t keepSize)
@@ -45,7 +44,8 @@ public:
void *buf = MyAlloc(newSize);
if (!buf)
return false;
memcpy(buf, _items, keepSize);
if (keepSize != 0)
memcpy(buf, _items, keepSize);
MyFree(_items);
_items = (Byte *)buf;
_size = newSize;
@@ -55,8 +55,8 @@ public:
CGrowBuf(): _items(0), _size(0) {}
~CGrowBuf() { MyFree(_items); }
operator Byte *() { return _items; };
operator const Byte *() const { return _items; };
operator Byte *() { return _items; }
operator const Byte *() const { return _items; }
size_t Size() const { return _size; }
};
@@ -135,10 +135,11 @@ public:
{
if (_fileMode)
return false;
if (Files.Size() < 1 || Files[0].IsAltStream || Files[0].IsDir)
if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir)
return false;
return true;
}
size_t GetMemStreamWrittenSize() const { return _pos; }
CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {}
@@ -165,6 +166,7 @@ public:
class CExtractCallbackImp:
public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback
public IOpenCallbackUI,
public IFolderArchiveExtractCallback2,
#ifndef _SFX
public IFolderOperationsExtractCallback,
public IFolderExtractToStreamCallback,
@@ -176,8 +178,10 @@ class CExtractCallbackImp:
public CMyUnknownImp
{
HRESULT MessageError(const char *message, const FString &path);
void Add_ArchiveName_Error();
public:
MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)
#ifndef _SFX
MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback)
MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback)
@@ -191,33 +195,12 @@ public:
INTERFACE_IProgress(;)
INTERFACE_IOpenCallbackUI(;)
// IFolderArchiveExtractCallback
INTERFACE_IFolderArchiveExtractCallback(;)
INTERFACE_IFolderArchiveExtractCallback2(;)
// STDMETHOD(SetTotalFiles)(UInt64 total);
// STDMETHOD(SetCompletedFiles)(const UInt64 *value);
STDMETHOD(AskOverwrite)(
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
Int32 *answer);
STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);
STDMETHOD(MessageError)(const wchar_t *message);
STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);
// IExtractCallbackUI
HRESULT BeforeOpen(const wchar_t *name);
HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);
HRESULT SetError(int level, const wchar_t *name,
UInt32 errorFlags, const wchar_t *errors,
UInt32 warningFlags, const wchar_t *warnings);
HRESULT ThereAreNoFiles();
HRESULT ExtractResult(HRESULT result);
HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType);
#ifndef _NO_CRYPTO
HRESULT SetPassword(const UString &password);
#endif
INTERFACE_IExtractCallbackUI(;)
#ifndef _SFX
// IFolderOperationsExtractCallback
@@ -295,6 +278,12 @@ public:
UString Password;
#endif
UString _lang_Extracting;
UString _lang_Testing;
UString _lang_Skipping;
UString _lang_Empty;
CExtractCallbackImp():
#ifndef _NO_CRYPTO
PasswordIsDefined(false),

View File

@@ -49,6 +49,9 @@ static UString g_MainPath;
static UString g_ArcFormat;
static bool g_Maximized = false;
// HRESULT LoadGlobalCodecs();
void FreeGlobalCodecs();
#ifndef UNDER_CE
DWORD g_ComCtl32Version;
@@ -568,6 +571,13 @@ static int WINAPI WinMain2(int nCmdShow)
if (!InitInstance (nCmdShow))
return FALSE;
// we will load Global_Codecs at first use instead.
/*
OutputDebugStringW(L"Before LoadGlobalCodecs");
LoadGlobalCodecs();
OutputDebugStringW(L"After LoadGlobalCodecs");
*/
#ifndef _UNICODE
if (g_IsNT)
{
@@ -597,6 +607,10 @@ static int WINAPI WinMain2(int nCmdShow)
}
}
// Destructor of g_CodecsReleaser can release DLLs.
// But we suppose that it's better to release DLLs here (before destructor).
FreeGlobalCodecs();
g_HWND = 0;
#ifndef UNDER_CE
OleUninitialize();
@@ -780,35 +794,45 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
xSizes[1] = 0;
g_App.CreateDragTarget();
bool archiveIsOpened;
bool encrypted;
bool needOpenFile = false;
if (!g_MainPath.IsEmpty() /* && g_OpenArchive */)
UString fullPath = g_MainPath;
if (!fullPath.IsEmpty() /* && g_OpenArchive */)
{
if (NFile::NFind::DoesFileExist(us2fs(g_MainPath)))
if (!NFile::NName::IsAbsolutePath(fullPath))
{
FString fullPathF;
if (NFile::NName::GetFullPath(us2fs(fullPath), fullPathF))
fullPath = fs2us(fullPathF);
}
if (NFile::NFind::DoesFileExist(us2fs(fullPath)))
needOpenFile = true;
}
HRESULT res = g_App.Create(hWnd, g_MainPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted);
HRESULT res = g_App.Create(hWnd, fullPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted);
if (res == E_ABORT)
{
return -1;
}
if (needOpenFile && !archiveIsOpened || res != S_OK)
{
UString message = L"Error";
if (res == S_FALSE || res == S_OK)
{
message = MyFormatNew(encrypted ?
IDS_CANT_OPEN_ENCRYPTED_ARCHIVE :
IDS_CANT_OPEN_ARCHIVE,
g_MainPath);
IDS_CANT_OPEN_ENCRYPTED_ARCHIVE :
IDS_CANT_OPEN_ARCHIVE,
fullPath);
}
else if (res != S_OK)
message = HResultToMessage(res);
ErrorMessage(message);
return -1;
}
// g_SplitterPos = 0;
// ::DragAcceptFiles(hWnd, TRUE);
@@ -816,6 +840,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
}
case WM_DESTROY:
{
// ::DragAcceptFiles(hWnd, FALSE);
@@ -839,11 +864,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
g_StartCaptureSplitterPos = g_Splitter.GetPos();
::SetCapture(hWnd);
break;
case WM_LBUTTONUP:
{
::ReleaseCapture();
break;
}
case WM_MOUSEMOVE:
{
if ((wParam & MK_LBUTTON) != 0 && ::GetCapture() == hWnd)
@@ -880,10 +907,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
break;
}
case WM_SETFOCUS:
// g_App.SetFocus(g_App.LastFocusedPanel);
g_App.SetFocusToLastItem();
break;
/*
case WM_ACTIVATE:
{
@@ -900,6 +929,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
}
*/
/*
case kLangWasChangedMessage:
MyLoadMenu();
@@ -910,11 +940,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_SETTINGCHANGE:
break;
*/
case WM_NOTIFY:
{
g_App.OnNotify((int)wParam, (LPNMHDR)lParam);
break;
}
/*
case WM_DROPFILES:
{

View File

@@ -219,6 +219,14 @@ SOURCE=.\Test.bmp
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\AltStreamsFolder.cpp
# End Source File
# Begin Source File
SOURCE=.\AltStreamsFolder.h
# End Source File
# Begin Source File
SOURCE=.\FSDrives.cpp
# End Source File
# Begin Source File
@@ -1026,6 +1034,10 @@ SOURCE=..\..\..\Windows\Window.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\Common.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\ComTry.h
# End Source File
# Begin Source File
@@ -1399,6 +1411,14 @@ SOURCE=..\GUI\HashGUI.cpp
SOURCE=..\GUI\HashGUI.h
# End Source File
# Begin Source File
SOURCE=..\GUI\UpdateCallbackGUI2.cpp
# End Source File
# Begin Source File
SOURCE=..\GUI\UpdateCallbackGUI2.h
# End Source File
# End Group
# End Group
# Begin Group "Compress"

View File

@@ -60,6 +60,7 @@ FM_OBJS = \
!IFNDEF UNDER_CE
FM_OBJS = $(FM_OBJS) \
$O\AltStreamsFolder.obj \
$O\FSDrives.obj \
$O\LinkDialog.obj \
$O\NetFolder.obj \

View File

@@ -11,6 +11,7 @@
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileIO.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/FileSystem.h"
#include "../../../Windows/PropVariant.h"
@@ -27,8 +28,8 @@ using namespace NWindows;
using namespace NFile;
using namespace NFind;
static CFSTR kVolPrefix = FTEXT("\\\\.\\");
static CFSTR kLongPrefix = FTEXT("\\\\?\\");
static const CFSTR kVolPrefix = FTEXT("\\\\.\\");
static const CFSTR kSuperPrefix = FTEXT("\\\\?\\");
FString CDriveInfo::GetDeviceFileIoName() const
{
@@ -53,6 +54,7 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
if (!inFile.GetLength(fileSize))
::GetLastError();
}
NIO::COutFile outFile;
if (writeToDisk)
{
@@ -62,6 +64,7 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
else
if (!outFile.Create(toPath, true))
return GetLastError();
CPhysTempBuffer tempBuffer;
tempBuffer.buffer = MidAlloc(bufferSize);
if (!tempBuffer.buffer)
@@ -93,12 +96,14 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
return E_FAIL;
pos += curSize;
}
return S_OK;
}
static const PROPID kProps[] =
{
kpidName,
// kpidOutName,
kpidTotalSize,
kpidFreeSpace,
kpidType,
@@ -107,7 +112,7 @@ static const PROPID kProps[] =
kpidClusterSize
};
static const char *kDriveTypes[] =
static const char * const kDriveTypes[] =
{
"Unknown"
, "No Root Dir"
@@ -219,6 +224,16 @@ STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT
{
case kpidIsDir: prop = !_volumeMode; break;
case kpidName: prop = di.Name; break;
case kpidOutName:
if (!di.Name.IsEmpty() && di.Name.Back() == ':')
{
FString s = di.Name;
s.DeleteBack();
AddExt(s, itemIndex);
prop = s;
}
break;
case kpidTotalSize: if (di.KnownSize) prop = di.DriveSize; break;
case kpidFreeSpace: if (di.KnownSizes) prop = di.FreeSpace; break;
case kpidClusterSize: if (di.KnownSizes) prop = di.ClusterSize; break;
@@ -240,14 +255,11 @@ HRESULT CFSDrives::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder)
return S_OK;
NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;
if (_longMode)
{
RINOK(fsFolderSpec->Init((FString)kLongPrefix + name, 0));
}
else
{
RINOK(fsFolderSpec->Init(name, 0));
}
FString path;
if (_superMode)
path = kSuperPrefix;
path += name;
RINOK(fsFolderSpec->Init(path));
*resultFolder = subFolder.Detach();
return S_OK;
}
@@ -295,8 +307,8 @@ STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value)
case kpidPath:
if (_volumeMode)
prop = kVolPrefix;
else if (_longMode)
prop = kLongPrefix;
else if (_superMode)
prop = kSuperPrefix;
else
prop = (UString)LangString(IDS_COMPUTER) + WCHAR_PATH_SEPARATOR;
break;
@@ -322,19 +334,20 @@ STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
return GetLastError();
}
const wchar_t *CFSDrives::GetExt(unsigned index) const
void CFSDrives::AddExt(FString &s, unsigned index) const
{
s += FTEXT('.');
const CDriveInfo &di = _drives[index];
const wchar_t *ext;
const char *ext;
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";
ext = "iso";
else if (di.FileSystemName.IsPrefixedBy_Ascii_NoCase("NTFS"))
ext = "ntfs";
else if (di.FileSystemName.IsPrefixedBy_Ascii_NoCase("FAT"))
ext = "fat";
else
ext = L"img";
return ext;
ext = "img";
s.AddAscii(ext);
}
HRESULT CFSDrives::GetFileSize(unsigned index, UInt64 &fileSize) const
@@ -352,12 +365,12 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
const wchar_t *path, IFolderOperationsExtractCallback *callback)
{
if (moveMode)
return E_NOTIMPL;
if (numItems == 0)
return S_OK;
if (moveMode)
return E_NOTIMPL;
if (!_volumeMode)
return E_NOTIMPL;
@@ -372,11 +385,14 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
RINOK(callback->SetTotal(totalSize));
RINOK(callback->SetNumFiles(numItems));
UString destPath = path;
FString destPath = us2fs(path);
if (destPath.IsEmpty())
return E_INVALIDARG;
bool directName = (destPath.Back() != WCHAR_PATH_SEPARATOR);
if (directName)
bool isAltDest = NName::IsAltPathPrefix(destPath);
bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
if (isDirectPath)
{
if (numItems > 1)
return E_INVALIDARG;
@@ -389,19 +405,19 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
{
unsigned index = indices[i];
const CDriveInfo &di = _drives[index];
UString destPath2 = destPath;
UString name = fs2us(di.Name);
if (!directName)
FString destPath2 = destPath;
if (!isDirectPath)
{
UString destName = name;
if (!destName.IsEmpty() && destName.Back() == L':')
FString destName = di.Name;
if (!destName.IsEmpty() && destName.Back() == ':')
{
destName.DeleteBack();
destName += L'.';
destName += GetExt(index);
AddExt(destName, index);
}
destPath2 += destName;
}
FString srcPath = di.GetDeviceFileIoName();
UInt64 fileSize = 0;
@@ -410,15 +426,23 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
return E_FAIL;
}
if (!di.KnownSize)
{
totalSize += fileSize;
RINOK(callback->SetTotal(totalSize));
RINOK(callback->SetTotal(totalSize));
}
Int32 writeAskResult;
CMyComBSTR destPathResult;
RINOK(callback->AskWrite(fs2us(srcPath), BoolToInt(false), NULL, &fileSize,
destPath2, &destPathResult, &writeAskResult));
fs2us(destPath2), &destPathResult, &writeAskResult));
if (!IntToBool(writeAskResult))
{
if (totalSize >= fileSize)
totalSize -= fileSize;
RINOK(callback->SetTotal(totalSize));
continue;
}
RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
@@ -427,11 +451,12 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
RINOK(CopyFileSpec(srcPath, us2fs(destPathResult), false, fileSize, bufferSize, completedSize, callback));
completedSize += fileSize;
}
return S_OK;
}
STDMETHODIMP CFSDrives::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
{
return E_NOTIMPL;
}

View File

@@ -36,10 +36,10 @@ class CFSDrives:
{
CObjectVector<CDriveInfo> _drives;
bool _volumeMode;
bool _longMode;
bool _superMode;
HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder);
const wchar_t *GetExt(unsigned index) const;
void AddExt(FString &s, unsigned index) const;
HRESULT GetFileSize(unsigned index, UInt64 &fileSize) const;
public:
MY_UNKNOWN_IMP2(IFolderGetSystemIconIndex, IFolderOperations)
@@ -49,10 +49,10 @@ public:
STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
void Init(bool volMode = false, bool longMode = false)
void Init(bool volMode = false, bool superMode = false)
{
_volumeMode = volMode;
_longMode = longMode;
_superMode = superMode;
}
};

View File

@@ -29,7 +29,7 @@
// But real support version for that function is NT 3.1 (probably)
// So we must define GetCompressedFileSizeW
EXTERN_C_BEGIN
WINBASEAPI DWORD WINAPI GetCompressedFileSizeW(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh );
WINBASEAPI DWORD WINAPI GetCompressedFileSizeW(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh);
EXTERN_C_END
#endif
#endif
@@ -68,20 +68,23 @@ static const Byte kProps[] =
kpidPrefix
};
HRESULT CFSFolder::Init(const FString &path, IFolderFolder *parentFolder)
HRESULT CFSFolder::Init(const FString &path /* , IFolderFolder *parentFolder */)
{
_parentFolder = 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 */);
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();
@@ -99,7 +102,7 @@ HRESULT CFsFolderStat::Enumerate()
{
RINOK(Progress->SetCompleted(NULL));
}
Path += FCHAR_PATH_SEPARATOR;
Path.Add_PathSepar();
unsigned len = Path.Len();
Path += FCHAR_ANY_MASK;
CEnumerator enumerator(Path);
@@ -124,7 +127,7 @@ HRESULT CFsFolderStat::Enumerate()
#ifndef UNDER_CE
static bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size)
bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size)
{
DWORD highPart;
DWORD lowPart = INVALID_FILE_SIZE;
@@ -140,10 +143,10 @@ static bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size)
#ifdef WIN_LONG_PATH
if (USE_SUPER_PATH)
{
UString longPath;
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
UString superPath;
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
{
lowPart = ::GetCompressedFileSizeW(longPath, &highPart);
lowPart = ::GetCompressedFileSizeW(superPath, &highPart);
if (lowPart != INVALID_FILE_SIZE || ::GetLastError() == NO_ERROR)
{
size = ((UInt64)highPart << 32) | lowPart;
@@ -279,11 +282,10 @@ bool CFSFolder::LoadComments()
if (len >= (1 << 28))
return false;
AString s;
char *p = s.GetBuffer((unsigned)((size_t)len + 1));
char *p = s.GetBuf((unsigned)(size_t)len);
UInt32 processedSize;
file.Read(p, (UInt32)len, processedSize);
p[len] = 0;
s.ReleaseBuffer();
s.ReleaseBuf_CalcLen((unsigned)(size_t)len);
if (processedSize != len)
return false;
file.Close();
@@ -293,14 +295,6 @@ bool CFSFolder::LoadComments()
return _comments.ReadFromString(unicodeString);
}
static bool IsAscii(const AString &s)
{
for (unsigned i = 0; i < s.Len(); i++)
if ((Byte)s[i] >= 0x80)
return false;
return true;
}
bool CFSFolder::SaveComments()
{
AString utf;
@@ -309,7 +303,7 @@ bool CFSFolder::SaveComments()
_comments.SaveToString(unicode);
ConvertUnicodeToUTF8(unicode, utf);
}
if (!IsAscii(utf))
if (!utf.IsAscii())
utf.Insert(0, "\xEF\xBB\xBF" "\r\n");
FString path = _path + kDescriptionFileName;
@@ -576,7 +570,7 @@ STDMETHODIMP CFSFolder::GetRawProp(UInt32
static inline CFSTR GetExtensionPtr(const FString &name)
{
int dotPos = name.ReverseFind(FTEXT('.'));
int dotPos = name.ReverseFind_Dot();
return name.Ptr((dotPos < 0) ? name.Len() : dotPos);
}
@@ -686,7 +680,7 @@ HRESULT CFSFolder::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder)
*resultFolder = 0;
CFSFolder *folderSpec = new CFSFolder;
CMyComPtr<IFolderFolder> subFolder = folderSpec;
RINOK(folderSpec->Init(_path + name + FCHAR_PATH_SEPARATOR, 0));
RINOK(folderSpec->Init(_path + name + FCHAR_PATH_SEPARATOR));
*resultFolder = subFolder.Detach();
return S_OK;
}
@@ -700,6 +694,7 @@ void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const
prefix.Empty();
}
*/
/*
void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const
{
@@ -714,20 +709,17 @@ void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const
parent = cur.Parent;
}
unsigned totalLen = len;
wchar_t *p = prefix.GetBuffer(len);
wchar_t *p = prefix.GetBuf_SetEnd(len) + len;
parent = item.Parent;
while (parent >= 0)
{
const CDirItem &cur = Files[parent];
// path = cur->Name + FCHAR_PATH_SEPARATOR + path;
MyStringCopy(p + len - cur.Name.Len() - 1, (const wchar_t *)cur.Name);
p[--len] = FCHAR_PATH_SEPARATOR;
len -= cur.Name.Len();
*(--p) = FCHAR_PATH_SEPARATOR;
p -= cur.Name.Len();
wmemcpy(p, cur.Name, cur.Name.Len());
parent = cur.Parent;
}
prefix.ReleaseBuffer(totalLen);
}
*/
@@ -752,24 +744,26 @@ STDMETHODIMP CFSFolder::BindToFolder(const wchar_t *name, IFolderFolder **result
return BindToFolderSpec(us2fs(name), resultFolder);
}
static CFSTR kLongPrefix = FTEXT("\\\\?\\");
static const CFSTR kSuperPrefix = FTEXT("\\\\?\\");
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(FCHAR_PATH_SEPARATOR);
int pos = _path.ReverseFind_PathSepar();
if (pos < 0 || pos != (int)_path.Len() - 1)
return E_FAIL;
FString parentPath = _path.Left(pos);
pos = parentPath.ReverseFind(FCHAR_PATH_SEPARATOR);
pos = parentPath.ReverseFind_PathSepar();
if (pos < 0)
{
#ifdef UNDER_CE
@@ -783,9 +777,10 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder)
return S_OK;
}
/*
parentPath.DeleteFrom(pos + 1);
if (parentPath == kLongPrefix)
if (parentPath == kSuperPrefix)
{
#ifdef UNDER_CE
*resultFolder = 0;
@@ -801,10 +796,10 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder)
FString parentPathReduced = parentPath.Left(pos);
#ifndef UNDER_CE
pos = parentPathReduced.ReverseFind(FCHAR_PATH_SEPARATOR);
pos = parentPathReduced.ReverseFind_PathSepar();
if (pos == 1)
{
if (parentPath[0] != FCHAR_PATH_SEPARATOR)
if (!IS_PATH_SEPAR_CHAR(parentPath[0]))
return E_FAIL;
CNetFolder *netFolderSpec = new CNetFolder;
CMyComPtr<IFolderFolder> netFolder = netFolderSpec;
@@ -818,6 +813,7 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder)
CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec;
RINOK(parentFolderSpec->Init(parentPath, 0));
*resultFolder = parentFolder.Detach();
*/
return S_OK;
}
@@ -837,7 +833,7 @@ STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop;
switch (propID)
{
case kpidType: prop = L"FSFolder"; break;
case kpidType: prop = "FSFolder"; break;
case kpidPath: prop = fs2us(_path); break;
}
prop.Detach(value);
@@ -874,7 +870,7 @@ STDMETHODIMP CFSFolder::Clone(IFolderFolder **resultFolder)
{
CFSFolder *fsFolderSpec = new CFSFolder;
CMyComPtr<IFolderFolder> folderNew = fsFolderSpec;
fsFolderSpec->Init(_path, 0);
fsFolderSpec->Init(_path);
*resultFolder = folderNew.Detach();
return S_OK;
}
@@ -1060,7 +1056,7 @@ STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID,
CTextPair pair;
pair.ID = filename;
pair.ID.Trim();
pair.Value = value->bstrVal;
pair.Value.SetFromBstr(value->bstrVal);
pair.Value.Trim();
if (pair.Value.IsEmpty())
_comments.DeletePair(filename);

View File

@@ -8,9 +8,10 @@
#include "../../../Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "IFolder.h"
#include "TextPairs.h"
#include "..\..\Archive\IArchive.h"
namespace NFsFolder {
@@ -133,7 +134,7 @@ private:
CObjectVector<CDirItem> Files;
FStringVector Folders;
// CObjectVector<CAltStream> Streams;
CMyComPtr<IFolderFolder> _parentFolder;
// CMyComPtr<IFolderFolder> _parentFolder;
bool _commentsAreLoaded;
CPairsStorage _comments;
@@ -158,9 +159,9 @@ private:
#endif
public:
HRESULT Init(const FString &path, IFolderFolder *parentFolder);
#ifdef UNDER_CE
HRESULT InitToRoot() { return Init(FTEXT("\\"), NULL); }
HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */);
#if !defined(_WIN32) || defined(UNDER_CE)
HRESULT InitToRoot() { return Init(FSTRING_PATH_SEPARATOR /* , NULL */); }
#endif
CFSFolder() : _flatMode(false)
@@ -178,6 +179,7 @@ public:
}
// void GetPrefix(const CDirItem &item, FString &prefix) const;
FString GetRelPath(const CDirItem &item) const;
void Clear()
@@ -188,6 +190,24 @@ public:
}
};
struct CCopyStateIO
{
IProgress *Progress;
UInt64 TotalSize;
UInt64 StartPos;
UInt64 CurrentSize;
bool DeleteSrcFile;
int ErrorFileIndex;
UString ErrorMessage;
CCopyStateIO(): DeleteSrcFile(false), TotalSize(0), StartPos(0) {}
HRESULT MyCopyFile(CFSTR inPath, CFSTR outPath);
};
HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName);
}
#endif

View File

@@ -29,6 +29,75 @@ extern bool g_IsNT;
namespace NFsFolder {
HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath)
{
ErrorFileIndex = -1;
ErrorMessage.Empty();
CurrentSize = 0;
{
const size_t kBufSize = 1 << 16;
CByteArr buf(kBufSize);
NIO::CInFile inFile;
NIO::COutFile outFile;
if (!inFile.Open(inPath))
{
ErrorFileIndex = 0;
return S_OK;
}
if (!outFile.Create(outPath, true))
{
ErrorFileIndex = 1;
return S_OK;
}
for (;;)
{
UInt32 num;
if (!inFile.Read(buf, kBufSize, num))
{
ErrorFileIndex = 0;
return S_OK;
}
if (num == 0)
break;
UInt32 written = 0;
if (!outFile.Write(buf, num, written))
{
ErrorFileIndex = 1;
return S_OK;
}
if (written != num)
{
ErrorMessage = L"Write error";
return S_OK;
}
CurrentSize += num;
if (Progress)
{
UInt64 completed = StartPos + CurrentSize;
RINOK(Progress->SetCompleted(&completed));
}
}
}
if (DeleteSrcFile)
{
if (!DeleteFileAlways(inPath))
{
ErrorFileIndex = 0;
return S_OK;
}
}
return S_OK;
}
/*
static bool IsItWindows2000orHigher()
{
@@ -43,8 +112,13 @@ static bool IsItWindows2000orHigher()
struct CProgressInfo
{
UInt64 TotalSize;
UInt64 StartPos;
UInt64 FileSize;
IProgress *Progress;
HRESULT ProgressResult;
void Init() { ProgressResult = S_OK; }
};
#ifndef PROGRESS_CONTINUE
@@ -71,7 +145,7 @@ DWORD
#endif
static DWORD CALLBACK CopyProgressRoutine(
LARGE_INTEGER /* TotalFileSize */, // file size
LARGE_INTEGER TotalFileSize, // file size
LARGE_INTEGER TotalBytesTransferred, // bytes transferred
LARGE_INTEGER /* StreamSize */, // bytes in stream
LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream
@@ -82,14 +156,27 @@ static DWORD CALLBACK CopyProgressRoutine(
LPVOID lpData // from CopyFileEx
)
{
CProgressInfo &progressInfo = *(CProgressInfo *)lpData;
UInt64 completed = progressInfo.StartPos + TotalBytesTransferred.QuadPart;
if (progressInfo.Progress->SetCompleted(&completed) != S_OK)
return PROGRESS_CANCEL;
return PROGRESS_CONTINUE;
TotalFileSize = TotalFileSize;
// TotalBytesTransferred = TotalBytesTransferred;
// StreamSize = StreamSize;
// StreamBytesTransferred = StreamBytesTransferred;
// dwStreamNumber = dwStreamNumber;
// dwCallbackReason = dwCallbackReason;
CProgressInfo &pi = *(CProgressInfo *)lpData;
if ((UInt64)TotalFileSize.QuadPart > pi.FileSize)
{
pi.TotalSize += (UInt64)TotalFileSize.QuadPart - pi.FileSize;
pi.FileSize = (UInt64)TotalFileSize.QuadPart;
pi.ProgressResult = pi.Progress->SetTotal(pi.TotalSize);
}
UInt64 completed = pi.StartPos + TotalBytesTransferred.QuadPart;
pi.ProgressResult = pi.Progress->SetCompleted(&completed);
return (pi.ProgressResult == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL);
}
typedef BOOL (WINAPI * CopyFileExPointer)(
typedef BOOL (WINAPI * Func_CopyFileExA)(
IN LPCSTR lpExistingFileName,
IN LPCSTR lpNewFileName,
IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
@@ -98,7 +185,7 @@ typedef BOOL (WINAPI * CopyFileExPointer)(
IN DWORD dwCopyFlags
);
typedef BOOL (WINAPI * CopyFileExPointerW)(
typedef BOOL (WINAPI * Func_CopyFileExW)(
IN LPCWSTR lpExistingFileName,
IN LPCWSTR lpNewFileName,
IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
@@ -107,67 +194,7 @@ typedef BOOL (WINAPI * CopyFileExPointerW)(
IN DWORD dwCopyFlags
);
static bool FsCopyFile(CFSTR oldFile, CFSTR newFile, IProgress *progress, UInt64 &completedSize)
{
CProgressInfo progressInfo;
progressInfo.Progress = progress;
progressInfo.StartPos = completedSize;
BOOL CancelFlag = FALSE;
#ifndef _UNICODE
if (g_IsNT)
#endif
{
const wchar_t *k_DllName =
#ifdef UNDER_CE
L"coredll.dll"
#else
L"kernel32.dll"
#endif
;
CopyFileExPointerW copyFunctionW = (CopyFileExPointerW)
My_GetProcAddress(::GetModuleHandleW(k_DllName), "CopyFileExW");
IF_USE_MAIN_PATH_2(oldFile, newFile)
{
if (copyFunctionW == 0)
return BOOLToBool(::CopyFileW(fs2us(oldFile), fs2us(newFile), TRUE));
if (copyFunctionW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine,
&progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS))
return true;
}
#ifdef WIN_LONG_PATH
if (USE_SUPER_PATH_2)
{
UString longPathExisting, longPathNew;
if (!GetSuperPaths(oldFile, newFile, longPathExisting, longPathNew, USE_MAIN_PATH_2))
return false;
if (copyFunctionW(longPathExisting, longPathNew, CopyProgressRoutine,
&progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS))
return true;
}
#endif
return false;
}
#ifndef _UNICODE
else
{
CopyFileExPointer copyFunction = (CopyFileExPointer)
::GetProcAddress(::GetModuleHandleA("kernel32.dll"),
"CopyFileExA");
if (copyFunction != 0)
{
if (copyFunction(fs2fas(oldFile), fs2fas(newFile),
CopyProgressRoutine,&progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS))
return true;
if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
return false;
}
return BOOLToBool(::CopyFile(fs2fas(oldFile), fs2fas(newFile), TRUE));
}
#endif
}
typedef BOOL (WINAPI * MoveFileWithProgressPointer)(
typedef BOOL (WINAPI * Func_MoveFileWithProgressW)(
IN LPCWSTR lpExistingFileName,
IN LPCWSTR lpNewFileName,
IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
@@ -175,42 +202,144 @@ typedef BOOL (WINAPI * MoveFileWithProgressPointer)(
IN DWORD dwFlags
);
#ifdef UNDER_CE
#define NON_CE_VAR(_v_)
#else
#define NON_CE_VAR(_v_) _v_
#endif
struct CCopyState
{
CProgressInfo ProgressInfo;
IFolderOperationsExtractCallback *Callback;
UInt64 TotalSize;
bool MoveMode;
bool UseReadWriteMode;
static bool FsMoveFile(CFSTR oldFile, CFSTR newFile,
IProgress * NON_CE_VAR(progress),
UInt64 & NON_CE_VAR(completedSize))
Func_CopyFileExW my_CopyFileExW;
#ifndef UNDER_CE
Func_MoveFileWithProgressW my_MoveFileWithProgressW;
#endif
#ifndef _UNICODE
Func_CopyFileExA my_CopyFileExA;
#endif
void Prepare();
bool CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile);
bool CopyFile_Sys(CFSTR oldFile, CFSTR newFile);
bool MoveFile_Sys(CFSTR oldFile, CFSTR newFile);
HRESULT CallProgress();
bool IsCallbackProgressError() { return ProgressInfo.ProgressResult != S_OK; }
};
HRESULT CCopyState::CallProgress()
{
return ProgressInfo.Progress->SetCompleted(&ProgressInfo.StartPos);
}
void CCopyState::Prepare()
{
my_CopyFileExW = NULL;
#ifndef UNDER_CE
my_MoveFileWithProgressW = NULL;
#endif
#ifndef _UNICODE
my_CopyFileExA = NULL;
if (!g_IsNT)
{
my_CopyFileExA = (Func_CopyFileExA)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "CopyFileExA");
}
else
#endif
{
HMODULE module = ::GetModuleHandleW(
#ifdef UNDER_CE
L"coredll.dll"
#else
L"kernel32.dll"
#endif
);
my_CopyFileExW = (Func_CopyFileExW)My_GetProcAddress(module, "CopyFileExW");
#ifndef UNDER_CE
my_MoveFileWithProgressW = (Func_MoveFileWithProgressW)My_GetProcAddress(module, "MoveFileWithProgressW");
#endif
}
}
/* WinXP-64:
CopyFileW(fromFile, toFile:altStream)
OK - there are NO alt streams in fromFile
ERROR_INVALID_PARAMETER - there are alt streams in fromFile
*/
bool CCopyState::CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile)
{
BOOL cancelFlag = FALSE;
if (my_CopyFileExW)
return BOOLToBool(my_CopyFileExW(oldFile, newFile, CopyProgressRoutine,
&ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS));
return BOOLToBool(::CopyFileW(oldFile, newFile, TRUE));
}
bool CCopyState::CopyFile_Sys(CFSTR oldFile, CFSTR newFile)
{
#ifndef _UNICODE
if (!g_IsNT)
{
if (my_CopyFileExA)
{
BOOL cancelFlag = FALSE;
if (my_CopyFileExA(fs2fas(oldFile), fs2fas(newFile),
CopyProgressRoutine, &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS))
return true;
if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
return false;
}
return BOOLToBool(::CopyFile(fs2fas(oldFile), fs2fas(newFile), TRUE));
}
else
#endif
{
IF_USE_MAIN_PATH_2(oldFile, newFile)
{
if (CopyFile_NT(fs2us(oldFile), fs2us(newFile)))
return true;
}
#ifdef WIN_LONG_PATH
if (USE_SUPER_PATH_2)
{
if (IsCallbackProgressError())
return false;
UString superPathOld, superPathNew;
if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
return false;
if (CopyFile_NT(superPathOld, superPathNew))
return true;
}
#endif
return false;
}
}
bool CCopyState::MoveFile_Sys(CFSTR oldFile, CFSTR newFile)
{
#ifndef UNDER_CE
// if (IsItWindows2000orHigher())
// {
CProgressInfo progressInfo;
progressInfo.Progress = progress;
progressInfo.StartPos = completedSize;
MoveFileWithProgressPointer moveFunction = (MoveFileWithProgressPointer)
My_GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")),
"MoveFileWithProgressW");
if (moveFunction != 0)
if (my_MoveFileWithProgressW)
{
IF_USE_MAIN_PATH_2(oldFile, newFile)
{
if (moveFunction(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine,
&progressInfo, MOVEFILE_COPY_ALLOWED))
if (my_MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine,
&ProgressInfo, MOVEFILE_COPY_ALLOWED))
return true;
}
#ifdef WIN_LONG_PATH
if ((!(USE_MAIN_PATH_2) || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) && USE_SUPER_PATH_2)
{
UString longPathExisting, longPathNew;
if (!GetSuperPaths(oldFile, newFile, longPathExisting, longPathNew, USE_MAIN_PATH_2))
if (IsCallbackProgressError())
return false;
if (moveFunction(longPathExisting, longPathNew, CopyProgressRoutine,
&progressInfo, MOVEFILE_COPY_ALLOWED))
UString superPathOld, superPathNew;
if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
return false;
if (my_MoveFileWithProgressW(superPathOld, superPathNew, CopyProgressRoutine,
&ProgressInfo, MOVEFILE_COPY_ALLOWED))
return true;
}
#endif
@@ -226,7 +355,10 @@ static bool FsMoveFile(CFSTR oldFile, CFSTR newFile,
static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
const wchar_t *message, const FString &fileName)
{
return callback->ShowMessage(message + fs2us(fileName));
UString s = message;
s += L" : ";
s += fs2us(fileName);
return callback->ShowMessage(s);
}
static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
@@ -235,41 +367,104 @@ static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
}
static HRESULT FsCopyFile(
static DWORD Return_LastError_or_FAIL()
{
DWORD errorCode = GetLastError();
if (errorCode == 0)
errorCode = (DWORD)E_FAIL;
return errorCode;
}
static UString GetLastErrorMessage()
{
return NError::MyFormatMessage(Return_LastError_or_FAIL());
}
HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName)
{
return SendMessageError(callback, GetLastErrorMessage(), fileName);
}
static HRESULT CopyFile_Ask(
CCopyState &state,
const FString &srcPath,
const CFileInfo &srcFileInfo,
const FString &destPathSpec,
IFolderOperationsExtractCallback *callback,
UInt64 &completedSize)
const FString &destPath)
{
FString destPath = destPathSpec;
if (CompareFileNames(destPath, srcPath) == 0)
{
RINOK(SendMessageError(callback, "can not copy file onto itself: ", destPath));
RINOK(SendMessageError(state.Callback,
state.MoveMode ?
"can not move file onto itself" :
"can not copy file onto itself"
, destPath));
return E_ABORT;
}
Int32 writeAskResult;
CMyComBSTR destPathResult;
RINOK(callback->AskWrite(
RINOK(state.Callback->AskWrite(
fs2us(srcPath),
BoolToInt(false),
&srcFileInfo.MTime, &srcFileInfo.Size,
fs2us(destPath),
&destPathResult,
&writeAskResult));
if (IntToBool(writeAskResult))
{
FString destPathNew = us2fs((const wchar_t *)(BSTR)destPathResult);
RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
if (!FsCopyFile(srcPath, destPathNew, callback, completedSize))
FString destPathNew = us2fs((LPCOLESTR)destPathResult);
RINOK(state.Callback->SetCurrentFilePath(fs2us(srcPath)));
if (state.UseReadWriteMode)
{
RINOK(SendMessageError(callback, NError::MyFormatMessage(GetLastError()) + L" : ", destPathNew));
return E_ABORT;
NFsFolder::CCopyStateIO state2;
state2.Progress = state.Callback;
state2.DeleteSrcFile = state.MoveMode;
state2.TotalSize = state.TotalSize;
state2.StartPos = state.ProgressInfo.StartPos;
RINOK(state2.MyCopyFile(srcPath, destPathNew));
if (state2.ErrorFileIndex >= 0)
{
if (state2.ErrorMessage.IsEmpty())
state2.ErrorMessage = GetLastErrorMessage();
FString errorName;
if (state2.ErrorFileIndex == 0)
errorName = srcPath;
else
errorName = destPathNew;
RINOK(SendMessageError(state.Callback, state2.ErrorMessage, errorName));
return E_ABORT;
}
state.ProgressInfo.StartPos += state2.CurrentSize;
}
else
{
state.ProgressInfo.FileSize = srcFileInfo.Size;
bool res;
if (state.MoveMode)
res = state.MoveFile_Sys(srcPath, destPathNew);
else
res = state.CopyFile_Sys(srcPath, destPathNew);
RINOK(state.ProgressInfo.ProgressResult);
if (!res)
{
// GetLastError() is ERROR_REQUEST_ABORTED in case of PROGRESS_CANCEL.
RINOK(SendMessageError(state.Callback, GetLastErrorMessage(), destPathNew));
return E_ABORT;
}
state.ProgressInfo.StartPos += state.ProgressInfo.FileSize;
}
}
completedSize += srcFileInfo.Size;
return callback->SetCompleted(&completedSize);
else
{
if (state.TotalSize >= srcFileInfo.Size)
{
state.TotalSize -= srcFileInfo.Size;
RINOK(state.ProgressInfo.Progress->SetTotal(state.TotalSize));
}
}
return state.CallProgress();
}
static FString CombinePath(const FString &folderPath, const FString &fileName)
@@ -288,123 +483,70 @@ static bool IsDestChild(const FString &src, const FString &dest)
}
static HRESULT CopyFolder(
const FString &srcPath,
const FString &destPath,
IFolderOperationsExtractCallback *callback,
UInt64 &completedSize)
CCopyState &state,
const FString &srcPath, // without TAIL separator
const FString &destPath) // without TAIL separator
{
RINOK(callback->SetCompleted(&completedSize));
RINOK(state.CallProgress());
if (IsDestChild(srcPath, destPath))
{
RINOK(SendMessageError(callback, "can not copy folder onto itself: ", destPath));
RINOK(SendMessageError(state.Callback,
state.MoveMode ?
"can not copy folder onto itself" :
"can not move folder onto itself"
, destPath));
return E_ABORT;
}
if (state.MoveMode)
{
if (state.MoveFile_Sys(srcPath, destPath))
return S_OK;
// MSDN: MoveFile() fails for dirs on different volumes.
}
if (!CreateComplexDir(destPath))
{
RINOK(SendMessageError(callback, "can not create folder: ", destPath));
RINOK(SendMessageError(state.Callback, "can not create folder", destPath));
return E_ABORT;
}
CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK));
CDirItem fi;
while (enumerator.Next(fi))
for (;;)
{
NFind::CFileInfo fi;
bool found;
if (!enumerator.Next(fi, found))
{
SendLastErrorMessage(state.Callback, srcPath);
return S_OK;
}
if (!found)
break;
const FString srcPath2 = CombinePath(srcPath, fi.Name);
const FString destPath2 = CombinePath(destPath, fi.Name);
if (fi.IsDir())
{
RINOK(CopyFolder(srcPath2, destPath2, callback, completedSize))
RINOK(CopyFolder(state, srcPath2, destPath2))
}
else
{
RINOK(FsCopyFile(srcPath2, fi, destPath2, callback, completedSize));
RINOK(CopyFile_Ask(state, srcPath2, fi, destPath2));
}
}
return S_OK;
}
/////////////////////////////////////////////////
// Move Operations
static HRESULT FsMoveFile(
const FString &srcPath,
const CFileInfo &srcFileInfo,
const FString &destPath,
IFolderOperationsExtractCallback *callback,
UInt64 &completedSize)
{
if (CompareFileNames(destPath, srcPath) == 0)
if (state.MoveMode)
{
RINOK(SendMessageError(callback, "can not move file onto itself: ", srcPath));
return E_ABORT;
}
Int32 writeAskResult;
CMyComBSTR destPathResult;
RINOK(callback->AskWrite(
fs2us(srcPath),
BoolToInt(false),
&srcFileInfo.MTime, &srcFileInfo.Size,
fs2us(destPath),
&destPathResult,
&writeAskResult));
if (IntToBool(writeAskResult))
{
FString destPathNew = us2fs((const wchar_t *)(BSTR)destPathResult);
RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
if (!FsMoveFile(srcPath, destPathNew, callback, completedSize))
if (!RemoveDir(srcPath))
{
RINOK(SendMessageError(callback, "can not move to file: ", destPathNew));
RINOK(SendMessageError(state.Callback, "can not remove folder", srcPath));
return E_ABORT;
}
}
completedSize += srcFileInfo.Size;
RINOK(callback->SetCompleted(&completedSize));
return S_OK;
}
static HRESULT FsMoveFolder(
const FString &srcPath,
const FString &destPath,
IFolderOperationsExtractCallback *callback,
UInt64 &completedSize)
{
if (IsDestChild(srcPath, destPath))
{
RINOK(SendMessageError(callback, "can not move folder onto itself: ", destPath));
return E_ABORT;
}
if (FsMoveFile(srcPath, destPath, callback, completedSize))
return S_OK;
if (!CreateComplexDir(destPath))
{
RINOK(SendMessageError(callback, "can not create folder: ", destPath));
return E_ABORT;
}
{
CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK));
CDirItem fi;
while (enumerator.Next(fi))
{
const FString srcPath2 = CombinePath(srcPath, fi.Name);
const FString destPath2 = CombinePath(destPath, fi.Name);
if (fi.IsDir())
{
RINOK(FsMoveFolder(srcPath2, destPath2, callback, completedSize));
}
else
{
RINOK(FsMoveFile(srcPath2, fi, destPath2, callback, completedSize));
}
}
}
if (!RemoveDir(srcPath))
{
RINOK(SendMessageError(callback, "can not remove folder: ", srcPath));
return E_ABORT;
}
return S_OK;
}
@@ -415,33 +557,44 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
if (numItems == 0)
return S_OK;
CFsFolderStat stat;
stat.Progress = callback;
RINOK(GetItemsFullSize(indices, numItems, stat));
RINOK(callback->SetTotal(stat.Size));
RINOK(callback->SetNumFiles(stat.NumFiles));
FString destPath = us2fs(path);
if (destPath.IsEmpty())
return E_INVALIDARG;
bool directName = (destPath.Back() != FCHAR_PATH_SEPARATOR);
if (directName)
bool isAltDest = NName::IsAltPathPrefix(destPath);;
bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
if (isDirectPath)
{
if (numItems > 1)
return E_INVALIDARG;
}
else
{
// Does CreateComplexDir work in network ?
if (!CreateComplexDir(destPath))
{
RINOK(SendMessageError(callback, "can not create folder: ", destPath));
return E_ABORT;
}
}
CFsFolderStat stat;
stat.Progress = callback;
RINOK(GetItemsFullSize(indices, numItems, stat));
if (stat.NumFolders != 0 && isAltDest)
return E_NOTIMPL;
RINOK(callback->SetTotal(stat.Size));
RINOK(callback->SetNumFiles(stat.NumFiles));
UInt64 completedSize = 0;
RINOK(callback->SetCompleted(&completedSize));
CCopyState state;
state.ProgressInfo.TotalSize = stat.Size;
state.ProgressInfo.TotalSize = stat.Size;
state.ProgressInfo.StartPos = 0;
state.ProgressInfo.Progress = callback;
state.ProgressInfo.Init();
state.Callback = callback;
state.MoveMode = IntToBool(moveMode);
state.UseReadWriteMode = isAltDest;
state.Prepare();
state.TotalSize = stat.Size;
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 index = indices[i];
@@ -449,38 +602,25 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
continue;
const CDirItem &fi = Files[index];
FString destPath2 = destPath;
if (!directName)
if (!isDirectPath)
destPath2 += fi.Name;
FString srcPath;
GetFullPath(fi, srcPath);
if (fi.IsDir())
{
if (moveMode)
{
RINOK(FsMoveFolder(srcPath, destPath2, callback, completedSize));
}
else
{
RINOK(CopyFolder(srcPath, destPath2, callback, completedSize));
}
RINOK(CopyFolder(state, srcPath, destPath2));
}
else
{
if (moveMode)
{
RINOK(FsMoveFile(srcPath, fi, destPath2, callback, completedSize));
}
else
{
RINOK(FsCopyFile(srcPath, fi, destPath2, callback, completedSize));
}
RINOK(CopyFile_Ask(state, srcPath, fi, destPath2));
}
}
return S_OK;
}
STDMETHODIMP CFSFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
{
/*
UInt64 numFolders, numFiles, totalSize;

View File

@@ -55,12 +55,10 @@ static int FindPlugin(const CObjectVector<CPluginInfo> &plugins, const UString &
}
*/
static const FChar kExtensionDelimiter = FTEXT('.');
static void SplitNameToPureNameAndExtension(const FString &fullName,
FString &pureName, FString &extensionDelimiter, FString &extension)
{
int index = fullName.ReverseFind(kExtensionDelimiter);
int index = fullName.ReverseFind_Dot();
if (index < 0)
{
pureName = fullName;
@@ -70,7 +68,7 @@ static void SplitNameToPureNameAndExtension(const FString &fullName,
else
{
pureName.SetFrom(fullName, index);
extensionDelimiter = kExtensionDelimiter;
extensionDelimiter = FTEXT('.');
extension = fullName.Ptr(index + 1);
}
}
@@ -89,7 +87,7 @@ HRESULT OpenFileFolderPlugin(
FString extension, name, pureName, dot;
int slashPos = path.ReverseFind(FCHAR_PATH_SEPARATOR);
int slashPos = path.ReverseFind_PathSepar();
FString dirPrefix;
FString fileName;
if (slashPos >= 0)

View File

@@ -11,7 +11,7 @@
int CExtDatabase::FindExt(const UString &ext)
{
FOR_VECTOR (i, Exts)
if (Exts[i].Ext.IsEqualToNoCase(ext))
if (Exts[i].Ext.IsEqualTo_NoCase(ext))
return i;
return -1;
}

View File

@@ -1,7 +1,7 @@
#include "FoldersPageRes.h"
#include "../../GuiCommon.rc"
#define xc 196
#define xc 240
#define yc 100
IDD_FOLDERS MY_PAGE

View File

@@ -36,6 +36,21 @@ FOLDER_INTERFACE(IFolderFolder, 0x00)
INTERFACE_FolderFolder(PURE)
};
/*
IFolderAltStreams::
BindToAltStreams((UInt32)(Int32)-1, ... ) means alt streams of that folder
*/
#define INTERFACE_FolderAltStreams(x) \
STDMETHOD(BindToAltStreams)(UInt32 index, IFolderFolder **resultFolder) x; \
STDMETHOD(BindToAltStreams)(const wchar_t *name, IFolderFolder **resultFolder) x; \
STDMETHOD(AreAltStreamsSupported)(UInt32 index, Int32 *isSupported) x; \
FOLDER_INTERFACE(IFolderAltStreams, 0x17)
{
INTERFACE_FolderAltStreams(PURE)
};
FOLDER_INTERFACE(IFolderWasChanged, 0x04)
{
STDMETHOD(WasChanged)(Int32 *wasChanged) PURE;
@@ -67,7 +82,7 @@ FOLDER_INTERFACE_SUB(IFolderOperationsExtractCallback, IProgress, 0x0B)
Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, \
const wchar_t *path, IFolderOperationsExtractCallback *callback) x; \
STDMETHOD(CopyFrom)(Int32 moveMode, const wchar_t *fromFolderPath, \
const wchar_t **itemsPaths, UInt32 numItems, IProgress *progress) x; \
const wchar_t * const *itemsPaths, UInt32 numItems, IProgress *progress) x; \
STDMETHOD(SetProperty)(UInt32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress) x; \
STDMETHOD(CopyFromFile)(UInt32 index, const wchar_t *fullFilePath, IProgress *progress) x; \

View File

@@ -63,8 +63,7 @@ bool CLangPage::OnInit()
if (!LangOpen(lang, dirPrefix + fi.Name))
{
if (!error.IsEmpty())
error += L' ';
error.Add_Space_if_NotEmpty();
error += fs2us(fi.Name);
continue;
}
@@ -80,7 +79,7 @@ bool CLangPage::OnInit()
index = (int)_langCombo.AddString(s);
_langCombo.SetItemData(index, _paths.Size());
_paths.Add(shortName);
if (g_LangID.IsEqualToNoCase(shortName))
if (g_LangID.IsEqualTo_NoCase(shortName))
_langCombo.SetCurSel(index);
}

View File

@@ -1,7 +1,7 @@
#include "LangPageRes.h"
#include "../../GuiCommon.rc"
#define xc 148
#define xc 160
#define yc 100
IDD_LANG DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT

View File

@@ -115,6 +115,11 @@ UString LangString(UInt32 langID)
return MyLoadString(langID);
}
void AddLangString(UString &s, UInt32 langID)
{
s += LangString(langID);
}
void LangString(UInt32 langID, UString &dest)
{
const wchar_t *s = g_Lang.Get(langID);
@@ -166,7 +171,7 @@ static void FindShortNames(UInt32 primeLang, UStringVector &names)
p++;
}
while (p != p2)
s += (wchar_t)*p++;
s += (wchar_t)(Byte)*p++;
names.Add(s);
}
p = p2 + 1;

View File

@@ -25,13 +25,15 @@ void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems);
void LangSetWindowText(HWND window, UInt32 langID);
UString LangString(UInt32 langID);
void AddLangString(UString &s, UInt32 langID);
void LangString(UInt32 langID, UString &dest);
void LangString_OnlyFromLangFile(UInt32 langID, UString &dest);
#else
inline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); }
inline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); }
inline void AddLangString(UString &s, UInt32 langID) { s += NWindows::MyLoadString(langID); }
#endif

View File

@@ -321,14 +321,14 @@ void CApp::Link()
int index = indices[0];
const UString itemName = srcPanel.GetItemName(index);
UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
UString path = srcPath;
{
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &destPanel = Panels[destPanelIndex];
if (NumPanels > 1)
if (destPanel.IsFSFolder())
path = destPanel._currentFolderPrefix;
path = destPanel.GetFsPath();
}
CLinkDialog dlg;

View File

@@ -1,7 +1,7 @@
#include "MenuPageRes.h"
#include "../../GuiCommon.rc"
#define xc 196
#define xc 240
#define yc 196
IDD_MENU MY_PAGE

View File

@@ -13,6 +13,7 @@
#include "App.h"
#include "HelpUtils.h"
#include "LangUtils.h"
#include "MyLoadMenu.h"
#include "RegistryUtils.h"
#include "resource.h"
@@ -100,19 +101,19 @@ public:
#define MIIM_FTYPE 0x00000100
#endif
static UINT Get_fMaskForString()
static UINT Get_fMask_for_String()
{
return g_IsNew_fMask ? MIIM_STRING : MIIM_TYPE;
}
static UINT Get_fMaskForFTypeAndString()
static UINT Get_fMask_for_FType_and_String()
{
return g_IsNew_fMask ? (MIIM_STRING | MIIM_FTYPE) : MIIM_TYPE;
}
*/
static inline UINT Get_fMaskForString() { return MIIM_TYPE; }
static inline UINT Get_fMaskForFTypeAndString() { return MIIM_TYPE; }
static inline UINT Get_fMask_for_String() { return MIIM_TYPE; }
static inline UINT Get_fMask_for_FType_and_String() { return MIIM_TYPE; }
static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex)
{
@@ -121,7 +122,7 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex)
for (int i = 0;; i++)
{
CMenuItem item;
item.fMask = Get_fMaskForString() | MIIM_SUBMENU | MIIM_ID;
item.fMask = Get_fMask_for_String() | MIIM_SUBMENU | MIIM_ID;
item.fType = MFT_STRING;
if (!menu.GetItem(i, true, item))
break;
@@ -157,14 +158,13 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex)
if (newString.IsEmpty())
continue;
UString shorcutString = item.StringValue;
int tabPos = shorcutString.ReverseFind(wchar_t('\t'));
int tabPos = item.StringValue.ReverseFind(L'\t');
if (tabPos >= 0)
newString += shorcutString.Ptr(tabPos);
newString += item.StringValue.Ptr(tabPos);
}
{
item.StringValue = newString;
item.fMask = Get_fMaskForString();
item.fMask = Get_fMask_for_String();
item.fType = MFT_STRING;
menu.SetItem(i, true, item);
}
@@ -203,7 +203,7 @@ static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec)
for (int i = 0;; i++)
{
CMenuItem item;
item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString();
item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String();
item.fType = MFT_STRING;
if (!srcMenu.GetItem(i, true, item))
@@ -307,13 +307,14 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)
subMenu.Attach(menu.GetSubMenu(0));
subMenu.RemoveAllItems();
int i;
for (i = 0; i < 10; i++)
{
UString s = LangString(IDS_BOOKMARK);
s += L' ';
s.Add_Space();
wchar_t c = (wchar_t)(L'0' + i);
s += c;
s += L"\tAlt+Shift+";
s.AddAscii("\tAlt+Shift+");
s += c;
subMenu.AppendItem(MF_STRING, kSetBookmarkMenuID + i, s);
}
@@ -332,7 +333,7 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)
}
if (s.IsEmpty())
s = L'-';
s += L"\tAlt+";
s.AddAscii("\tAlt+");
s += (wchar_t)(L'0' + i);
menu.AppendItem(MF_STRING, kOpenBookmarkMenuID + i, s);
}
@@ -348,8 +349,7 @@ void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id)
}
*/
void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu,
bool isFsFolder, int numItems, bool allAreFiles)
void CFileMenu::Load(HMENU hMenu, unsigned startPos)
{
CMenu destMenu;
destMenu.Attach(hMenu);
@@ -357,15 +357,17 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu,
UString diffPath;
ReadRegDiff(diffPath);
int numRealItems = startPos;
for (int i = 0;; i++)
unsigned numRealItems = startPos;
for (unsigned i = 0;; i++)
{
CMenuItem item;
item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString();
item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String();
item.fType = MFT_STRING;
if (!g_FileMenu.GetItem(i, true, item))
break;
{
if (!programMenu && item.wID == IDCLOSE)
continue;
@@ -376,6 +378,26 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu,
bool isOneFsFile = (isFsFolder && numItems == 1 && allAreFiles);
bool disable = (!isOneFsFile && (item.wID == IDM_SPLIT || item.wID == IDM_COMBINE));
if (readOnly)
{
switch (item.wID)
{
case IDM_RENAME:
case IDM_MOVE_TO:
case IDM_DELETE:
case IDM_COMMENT:
case IDM_CREATE_FOLDER:
case IDM_CREATE_FILE:
disable = true;
}
}
if (item.wID == IDM_LINK && numItems != 1)
disable = true;
if (item.wID == IDM_ALT_STREAMS)
disable = !isAltStreamsSupported;
bool isBigScreen = NControl::IsDialogSizeOK(40, 200);
if (!isBigScreen && (disable || item.IsSeparator()))
@@ -434,6 +456,7 @@ bool ExecuteFileCommand(int id)
case IDM_CREATE_FILE: g_App.CreateFile(); break;
#ifndef UNDER_CE
case IDM_LINK: g_App.Link(); break;
case IDM_ALT_STREAMS: g_App.OpenAltStreams(); break;
#endif
default: return false;
}

View File

@@ -9,8 +9,28 @@ void OnMenuActivating(HWND hWnd, HMENU hMenu, int position);
bool OnMenuCommand(HWND hWnd, int id);
void MyLoadMenu();
void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu,
bool isFsFolder, int numItems, bool allAreFiles);
struct CFileMenu
{
bool programMenu;
bool readOnly;
bool isFsFolder;
bool allAreFiles;
bool isAltStreamsSupported;
int numItems;
CFileMenu():
programMenu(false),
readOnly(false),
isFsFolder(false),
allAreFiles(false),
isAltStreamsSupported(true),
numItems(0)
{}
void Load(HMENU hMenu, unsigned startPos);
};
bool ExecuteFileCommand(int id);
#endif

View File

@@ -73,7 +73,15 @@ void CNetFolder::Init(const NWindows::NNet::CResourceW *netResource,
_netResourcePointer = &_netResource;
// if (_netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER)
_path = _netResource.RemoteName + WCHAR_PATH_SEPARATOR;
_path = _netResource.RemoteName;
/* WinXP-64: When we move UP from Network share without _parentFolder chain,
we can get empty _netResource.RemoteName. Do we need to use Provider there ? */
if (_path.IsEmpty())
_path = _netResource.Provider;
if (!_path.IsEmpty())
_path.Add_PathSepar();
}
_parentFolder = parentFolder;
}
@@ -111,7 +119,7 @@ STDMETHODIMP CNetFolder::LoadItems()
if (!resource.RemoteNameIsDefined) // For Win 98, I don't know what's wrong
resource.RemoteName = resource.Comment;
resource.Name = resource.RemoteName;
int pos = resource.Name.ReverseFind(WCHAR_PATH_SEPARATOR);
int pos = resource.Name.ReverseFind_PathSepar();
if (pos >= 0)
{
// _path = resource.Name.Left(pos + 1);
@@ -186,7 +194,7 @@ STDMETHODIMP CNetFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder
{
NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;
RINOK(fsFolderSpec->Init(us2fs(resource.RemoteName + WCHAR_PATH_SEPARATOR), this));
RINOK(fsFolderSpec->Init(us2fs(resource.RemoteName + WCHAR_PATH_SEPARATOR))); // , this
*resultFolder = subFolder.Detach();
}
else
@@ -237,7 +245,7 @@ STDMETHODIMP CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidType: prop = L"NetFolder"; break;
case kpidType: prop = "NetFolder"; break;
case kpidPath: prop = _path; break;
}
prop.Detach(value);

View File

@@ -50,7 +50,7 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID,
sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size));
const UString &fileName = fileInfo.Name;
int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR);
int slashPos = fileName.ReverseFind_PathSepar();
UString s1 = fileName.Left(slashPos + 1);
UString s2 = fileName.Ptr(slashPos + 1);
@@ -58,18 +58,18 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID,
ReduceString(s2);
UString s = s1;
s += L'\n';
s.Add_LF();
s += s2;
s += L'\n';
s.Add_LF();
s += sizeString;
s += L'\n';
s.Add_LF();
if (fileInfo.TimeIsDefined)
{
FILETIME localFileTime;
if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))
throw 4190402;
s += LangString(IDS_PROP_MTIME);
AddLangString(s, IDS_PROP_MTIME);
s += L": ";
wchar_t t[32];
ConvertFileTimeToString(localFileTime, t);

View File

@@ -477,7 +477,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
_comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit));
_comboBoxEdit._panel = this;
#ifndef _UNICODE
if(g_IsNT)
if (g_IsNT)
_comboBoxEdit._origWindowProc =
(WNDPROC)_comboBoxEdit.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));
else
@@ -675,7 +675,7 @@ void CPanel::MessageBoxError2Lines(LPCWSTR message, HRESULT errorCode)
UString m = message;
if (errorCode != 0)
{
m += L'\n';
m.Add_LF();
m += HResultToMessage(errorCode);
}
MessageBoxMyError(m);
@@ -708,29 +708,32 @@ void CPanel::SetFocusToLastRememberedItem()
UString CPanel::GetFolderTypeID() const
{
NCOM::CPropVariant prop;
if (_folder->GetFolderProperty(kpidType, &prop) == S_OK)
if (prop.vt == VT_BSTR)
return (const wchar_t *)prop.bstrVal;
return L"";
{
NCOM::CPropVariant prop;
if (_folder->GetFolderProperty(kpidType, &prop) == S_OK)
if (prop.vt == VT_BSTR)
return (const wchar_t *)prop.bstrVal;
}
return UString();
}
bool CPanel::IsFolderTypeEqTo(const wchar_t *s) const
bool CPanel::IsFolderTypeEqTo(const char *s) const
{
return GetFolderTypeID() == s;
return StringsAreEqual_Ascii(GetFolderTypeID(), s);
}
bool CPanel::IsRootFolder() const { return IsFolderTypeEqTo(L"RootFolder"); }
bool CPanel::IsFSFolder() const { return IsFolderTypeEqTo(L"FSFolder"); }
bool CPanel::IsFSDrivesFolder() const { return IsFolderTypeEqTo(L"FSDrives"); }
bool CPanel::IsRootFolder() const { return IsFolderTypeEqTo("RootFolder"); }
bool CPanel::IsFSFolder() const { return IsFolderTypeEqTo("FSFolder"); }
bool CPanel::IsFSDrivesFolder() const { return IsFolderTypeEqTo("FSDrives"); }
bool CPanel::IsAltStreamsFolder() const { return IsFolderTypeEqTo("AltStreamsFolder"); }
bool CPanel::IsArcFolder() const
{
return GetFolderTypeID().IsPrefixedBy(L"7-Zip");
return GetFolderTypeID().IsPrefixedBy_Ascii_NoCase("7-Zip");
}
UString CPanel::GetFsPath() const
{
if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix())
if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix() && !IsSuperDrivesPrefix())
return UString();
return _currentFolderPrefix;
}
@@ -744,12 +747,6 @@ UString CPanel::GetDriveOrNetworkPrefix() const
return drive;
}
bool CPanel::DoesItSupportOperations() const
{
CMyComPtr<IFolderOperations> folderOperations;
return _folder.QueryInterface(IID_IFolderOperations, &folderOperations) == S_OK;
}
void CPanel::SetListViewMode(UInt32 index)
{
if (index >= 4)
@@ -805,7 +802,7 @@ void CPanel::AddToArchive()
{
CRecordVector<UInt32> indices;
GetOperatedItemIndices(indices);
if (!IsFsOrDrivesFolder())
if (!Is_IO_FS_Folder())
{
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
@@ -817,20 +814,16 @@ void CPanel::AddToArchive()
}
UStringVector names;
UString curPrefix = _currentFolderPrefix;
UString destCurDirPrefix = _currentFolderPrefix;
const UString curPrefix = GetFsPath();
UString destCurDirPrefix = curPrefix;
if (IsFSDrivesFolder())
{
destCurDirPrefix = ROOT_FS_FOLDER;
if (!IsDeviceDrivesPrefix())
curPrefix.Empty();
}
FOR_VECTOR (i, indices)
names.Add(curPrefix + GetItemRelPath(indices[i]));
names.Add(curPrefix + GetItemRelPath2(indices[i]));
bool fromPrev = (names.Size() > 1);
const UString archiveName = CreateArchiveName(names.Front(), fromPrev, false);
HRESULT res = CompressFiles(destCurDirPrefix, archiveName, L"",
const UString arcName = CreateArchiveName(names.Front(), fromPrev, false);
HRESULT res = CompressFiles(destCurDirPrefix, arcName, L"",
true, // addExtension
names, false, true, false);
if (res != S_OK)
@@ -841,23 +834,24 @@ void CPanel::AddToArchive()
// KillSelection();
}
static UString GetSubFolderNameForExtract(const UString &archiveName)
static UString GetSubFolderNameForExtract(const UString &arcPath)
{
UString res = archiveName;
int slashPos = res.ReverseFind(WCHAR_PATH_SEPARATOR);
int dotPos = res.ReverseFind(L'.');
if (dotPos < 0 || slashPos > dotPos)
res += L'~';
UString s = arcPath;
int slashPos = s.ReverseFind_PathSepar();
int dotPos = s.ReverseFind_Dot();
if (dotPos <= slashPos + 1)
s += L'~';
else
{
res.DeleteFrom(dotPos);
res.TrimRight();
s.DeleteFrom(dotPos);
s.TrimRight();
}
return res;
return s;
}
void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &paths, bool allowFolders)
{
const UString prefix = GetFsPath();
FOR_VECTOR (i, indices)
{
int index = indices[i];
@@ -866,7 +860,7 @@ void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &p
paths.Clear();
break;
}
paths.Add(GetItemFullPath(index));
paths.Add(prefix + GetItemRelPath2(index));
}
if (paths.Size() == 0)
{
@@ -888,26 +882,31 @@ void CPanel::ExtractArchives()
GetFilePaths(indices, paths);
if (paths.IsEmpty())
return;
UString folderName;
UString outFolder = GetFsPath();
if (indices.Size() == 1)
folderName = GetSubFolderNameForExtract(GetItemRelPath(indices[0]));
outFolder += GetSubFolderNameForExtract(GetItemRelPath(indices[0]));
else
folderName = L"*";
::ExtractArchives(paths, _currentFolderPrefix + folderName + UString(WCHAR_PATH_SEPARATOR)
outFolder += L'*';
outFolder.Add_PathSepar();
::ExtractArchives(paths, outFolder
, true // showDialog
, false // elimDup
);
}
void AddValuePair(UINT resourceID, UInt64 value, UString &s)
/*
static void AddValuePair(UINT resourceID, UInt64 value, UString &s)
{
wchar_t sz[32];
s += LangString(resourceID);
AddLangString(s, resourceID);
char sz[32];
s += L": ";
ConvertUInt64ToString(value, sz);
s += sz;
s += L'\n';
s.AddAsciiStr(sz);
s.Add_LF();
}
*/
class CThreadTest: public CProgressThreadVirt
{
@@ -939,8 +938,8 @@ HRESULT CThreadTest::ProcessVirt()
AddValuePair(IDS_PROP_FILES, ExtractCallbackSpec->NumFiles, s);
// AddValuePair(IDS_PROP_SIZE, ExtractCallbackSpec->UnpackSize, s);
// AddSizePair(IDS_COMPRESSED_COLON, Stat.PackSize, s);
s += L'\n';
s += LangString(IDS_MESSAGE_NO_ERRORS);
s.Add_LF();
AddLangString(s, IDS_MESSAGE_NO_ERRORS);
FinalMessage.OkMessage.Message = s;
}
return S_OK;
@@ -948,18 +947,18 @@ HRESULT CThreadTest::ProcessVirt()
*/
/*
static void AddSizePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s)
static void AddSizePair(UInt32 langID, UInt64 value, UString &s)
{
wchar_t sz[32];
s += LangString(resourceID, langID);
char sz[32];
AddLangString(s, langID);
s += L' ';
ConvertUInt64ToString(value, sz);
s += sz;
s.AddAsciiStr(sz);
ConvertUInt64ToString(value >> 20, sz);
s += L" (";
s += sz;
s += L" MB)";
s += L'\n';
s.AddAsciiStr(" (");
s.AddAsciiStr(sz);
s.AddAsciiStr(" MB)");
s.Add_LF();
}
*/

View File

@@ -11,6 +11,7 @@
#include "../../../Windows/DLL.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/Handle.h"
#include "../../../Windows/Synchronization.h"
@@ -43,10 +44,10 @@ const int kParentFolderID = 100;
const int kParentIndex = -1;
#ifdef UNDER_CE
#if !defined(_WIN32) || defined(UNDER_CE)
#define ROOT_FS_FOLDER L"\\"
#else
#define ROOT_FS_FOLDER L"C:\\\\"
#define ROOT_FS_FOLDER L"C:\\"
#endif
struct CPanelCallback
@@ -117,12 +118,13 @@ struct CTempFileInfo
struct CFolderLink: public CTempFileInfo
{
NWindows::NDLL::CLibrary Library;
CMyComPtr<IFolderFolder> ParentFolder;
CMyComPtr<IFolderFolder> ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0])
UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level)
bool UsePassword;
UString Password;
bool IsVirtual;
UString VirtualPath;
UString VirtualPath; // without tail slash
CFolderLink(): UsePassword(false), IsVirtual(false) {}
bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const
@@ -146,7 +148,7 @@ enum MyMessages
#endif
};
UString GetFolderPath(IFolderFolder * folder);
UString GetFolderPath(IFolderFolder *folder);
class CPanel;
@@ -380,27 +382,11 @@ public:
CMyComPtr<IFolderCompare> _folderCompare;
CMyComPtr<IFolderGetItemName> _folderGetItemName;
CMyComPtr<IArchiveGetRawProps> _folderRawProps;
CMyComPtr<IFolderAltStreams> _folderAltStreams;
CMyComPtr<IFolderOperations> _folderOperations;
void ReleaseFolder()
{
_folderCompare.Release();
_folderGetItemName.Release();
_folderRawProps.Release();
_folder.Release();
_thereAreDeletedItems = false;
}
void SetNewFolder(IFolderFolder *newFolder)
{
ReleaseFolder();
_folder = newFolder;
if (_folder)
{
_folder.QueryInterface(IID_IFolderCompare, &_folderCompare);
_folder.QueryInterface(IID_IFolderGetItemName, &_folderGetItemName);
_folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps);
}
}
void ReleaseFolder();
void SetNewFolder(IFolderFolder *newFolder);
// CMyComPtr<IFolderGetSystemIconIndex> _folderGetSystemIconIndex;
@@ -417,9 +403,11 @@ public:
bool IsItem_AltStream(int itemIndex) const;
UString GetItemName(int itemIndex) const;
void GetItemNameFast(int itemIndex, UString &s) const;
UString GetItemName_for_Copy(int itemIndex) const;
void GetItemName(int itemIndex, UString &s) const;
UString GetItemPrefix(int itemIndex) const;
UString GetItemRelPath(int itemIndex) const;
UString GetItemRelPath2(int itemIndex) const;
UString GetItemFullPath(int itemIndex) const;
UInt64 GetItemSize(int itemIndex) const;
@@ -438,6 +426,7 @@ public:
void LoadFullPathAndShow();
void FoldersHistory();
void OpenParentFolder();
void CloseOneLevel();
void CloseOpenFolders();
void OpenRootFolder();
@@ -554,19 +543,65 @@ public:
void KillSelection();
UString GetFolderTypeID() const;
bool IsFolderTypeEqTo(const wchar_t *s) const;
bool IsFolderTypeEqTo(const char *s) const;
bool IsRootFolder() const;
bool IsFSFolder() const;
bool IsFSDrivesFolder() const;
bool IsAltStreamsFolder() const;
bool IsArcFolder() const;
bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); }
/*
c:\Dir
Computer\
\\?\
\\.\
*/
bool Is_IO_FS_Folder() const
{
return IsFSFolder() || IsFSDrivesFolder() || IsAltStreamsFolder();
}
bool Is_Slow_Icon_Folder() const
{
return IsFSFolder() || IsAltStreamsFolder();
}
// bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); }
bool IsDeviceDrivesPrefix() const { return _currentFolderPrefix == L"\\\\.\\"; }
bool IsSuperDrivesPrefix() const { return _currentFolderPrefix == L"\\\\?\\"; }
/*
c:\Dir
Computer\
\\?\
*/
bool IsFsOrPureDrivesFolder() const { return IsFSFolder() || (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()); }
/*
c:\Dir
Computer\
\\?\
\\SERVER\
*/
bool IsFolder_with_FsItems() const
{
if (IsFsOrPureDrivesFolder())
return true;
#if defined(_WIN32) && !defined(UNDER_CE)
FString prefix = us2fs(GetFsPath());
return (prefix.Len() == NWindows::NFile::NName::GetNetworkServerPrefixSize(prefix));
#else
return false;
#endif
}
UString GetFsPath() const;
UString GetDriveOrNetworkPrefix() const;
bool DoesItSupportOperations() const;
bool DoesItSupportOperations() const { return _folderOperations != NULL; }
bool IsThereReadOnlyFolder() const;
bool CheckBeforeUpdate(UINT resourceID);
bool _processTimer;
bool _processNotify;
@@ -574,58 +609,56 @@ public:
class CDisableTimerProcessing
{
bool _processTimerMem;
CLASS_NO_COPY(CDisableTimerProcessing);
bool _processTimer;
CPanel &_panel;
CDisableTimerProcessing(const CDisableTimerProcessing &);
CDisableTimerProcessing& operator=(const CDisableTimerProcessing &);
public:
CDisableTimerProcessing(CPanel &panel): _panel(panel) { Disable(); }
~CDisableTimerProcessing() { Restore(); }
void Disable()
{
_processTimerMem = _panel._processTimer;
_processTimer = _panel._processTimer;
_panel._processTimer = false;
}
void Restore()
{
_panel._processTimer = _processTimerMem;
_panel._processTimer = _processTimer;
}
};
class CDisableNotify
{
bool _processNotifyMem;
bool _processStatusBarMem;
CLASS_NO_COPY(CDisableNotify);
bool _processNotify;
bool _processStatusBar;
CPanel &_panel;
CDisableNotify(const CDisableNotify &);
CDisableNotify& operator=(const CDisableNotify &);
public:
CDisableNotify(CPanel &panel): _panel(panel) { Disable(); }
~CDisableNotify() { Restore(); }
void Disable()
{
_processNotifyMem = _panel._processNotify;
_processStatusBarMem = _panel._processStatusBar;
_processNotify = _panel._processNotify;
_processStatusBar = _panel._processStatusBar;
_panel._processNotify = false;
_panel._processStatusBar = false;
}
void SetMemMode_Enable()
{
_processNotifyMem = true;
_processStatusBarMem = true;
_processNotify = true;
_processStatusBar = true;
}
void Restore()
{
_panel._processNotify = _processNotifyMem;
_panel._processStatusBar = _processStatusBarMem;
_panel._processNotify = _processNotify;
_panel._processStatusBar = _processStatusBar;
}
};
@@ -647,10 +680,12 @@ public:
void MessageBoxLastError(LPCWSTR caption);
void MessageBoxLastError();
void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID);
// void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID);
void MessageBoxErrorLang(UINT resourceID);
void OpenAltStreams();
void OpenFocusedItemAsInternal();
void OpenSelectedItems(bool internal);

View File

@@ -1,4 +1,4 @@
/// PanelExtract.cpp
/// PanelCopy.cpp
#include "StdAfx.h"
@@ -79,18 +79,25 @@ HRESULT CPanelCopyThread::ProcessVirt()
return Result;
}
/*
#ifdef EXTERNAL_CODECS
static void ThrowException_if_Error(HRESULT res)
{
if (res != S_OK)
throw CSystemException(res);
}
#endif
*/
HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &indices,
UStringVector *messages,
bool &usePassword, UString &password)
{
CMyComPtr<IFolderOperations> folderOperations;
if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
if (!_folderOperations)
{
UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
if (options.showErrorMessages)
@@ -100,8 +107,17 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
return E_FAIL;
}
HRESULT res;
HRESULT res = S_OK;
{
/*
#ifdef EXTERNAL_CODECS
CExternalCodecs g_ExternalCodecs;
#endif
*/
/* extracter.Hash uses g_ExternalCodecs
extracter must be declared after g_ExternalCodecs for correct destructor order !!! */
CPanelCopyThread extracter;
extracter.ExtractCallbackSpec = new CExtractCallbackImp;
@@ -113,11 +129,6 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
extracter.ExtractCallbackSpec->StreamMode = options.streamMode;
#ifdef EXTERNAL_CODECS
CExternalCodecs __externalCodecs;
#else
CMyComPtr<IUnknown> compressCodecsInfo;
#endif
if (indices.Size() == 1)
extracter.FirstFilePath = GetItemRelPath(indices[0]);
@@ -131,19 +142,16 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
if (!options.hashMethods.IsEmpty())
{
{
CCodecs *codecs = new CCodecs;
ThrowException_if_Error(codecs->Load());
#ifdef EXTERNAL_CODECS
__externalCodecs.GetCodecs = codecs;
__externalCodecs.GetHashers = codecs;
ThrowException_if_Error(__externalCodecs.LoadCodecs());
#else
compressCodecsInfo = codecs;
#endif
}
/* this code is used when we call CRC calculation for files in side archive
But new code uses global codecs so we don't need to call LoadGlobalCodecs again */
extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS options.hashMethods);
/*
#ifdef EXTERNAL_CODECS
ThrowException_if_Error(LoadGlobalCodecs());
#endif
*/
extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS_G options.hashMethods);
extracter.ExtractCallbackSpec->SetHashMethods(&extracter.Hash);
}
else if (options.testMode)
@@ -153,7 +161,6 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
extracter.Hash.Init();
UString title;
{
UInt32 titleID = IDS_COPYING;
@@ -185,7 +192,7 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAsk;
extracter.ExtractCallbackSpec->Init();
extracter.Indices = indices;
extracter.FolderOperations = folderOperations;
extracter.FolderOperations = _folderOperations;
extracter.ExtractCallbackSpec->PasswordIsDefined = usePassword;
extracter.ExtractCallbackSpec->Password = password;
@@ -244,10 +251,8 @@ struct CThreadUpdate
HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths,
bool showErrorMessages, UStringVector *messages)
{
CMyComPtr<IFolderOperations> folderOperations;
_folder.QueryInterface(IID_IFolderOperations, &folderOperations);
HRESULT res;
if (!folderOperations)
if (!_folderOperations)
res = E_NOINTERFACE;
else
{
@@ -255,6 +260,7 @@ HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStri
updater.MoveMode = moveMode;
updater.UpdateCallbackSpec = new CUpdateCallback100Imp;
updater.UpdateCallback = updater.UpdateCallbackSpec;
updater.UpdateCallbackSpec->Init();
updater.UpdateCallbackSpec->ProgressDialog = &updater.ProgressDialog;
@@ -263,10 +269,18 @@ HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStri
updater.ProgressDialog.MainWindow = GetParent();
updater.ProgressDialog.MainTitle = progressWindowTitle;
updater.ProgressDialog.MainAddTitle = title + UString(L' ');
updater.ProgressDialog.MainAddTitle = title + L' ';
updater.UpdateCallbackSpec->Init(false, L"");
updater.FolderOperations = folderOperations;
{
if (!_parentFolders.IsEmpty())
{
const CFolderLink &fl = _parentFolders.Back();
updater.UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword;
updater.UpdateCallbackSpec->Password = fl.Password;
}
}
updater.FolderOperations = _folderOperations;
updater.FolderPrefix = folderPrefix;
updater.FileNames.ClearAndReserve(filePaths.Size());
unsigned i;

View File

@@ -6,6 +6,7 @@
#include "../../../Windows/FileFind.h"
#include "../../../Windows/FileIO.h"
#include "../../../Windows/FileName.h"
#include "../Common/LoadCodecs.h"
@@ -19,12 +20,18 @@
using namespace NWindows;
using namespace NFile;
#ifdef EXTERNAL_CODECS
extern CExternalCodecs g_ExternalCodecs;
HRESULT LoadGlobalCodecs();
#endif
static const UInt32 kBufSize = (1 << 15);
struct CDirEnumerator
{
bool EnterToDirs;
FString BasePrefix;
FString BasePrefix_for_Open;
FStringVector FilePaths;
CObjectVector<NFind::CEnumerator> Enumerators;
@@ -54,22 +61,27 @@ DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &r
{
filled = false;
resPath.Empty();
for (;;)
{
#if defined(_WIN32) && !defined(UNDER_CE)
bool isRootPrefix = (BasePrefix.IsEmpty() || (NName::IsSuperPath(BasePrefix) && BasePrefix[NName::kSuperPathPrefixSize] == 0));
#endif
if (Enumerators.IsEmpty())
{
if (Index >= FilePaths.Size())
return S_OK;
const FString &path = FilePaths[Index++];
int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR);
int pos = path.ReverseFind_PathSepar();
if (pos >= 0)
resPath.SetFrom(path, pos + 1);
#ifdef _WIN32
if (BasePrefix.IsEmpty() && path.Len() == 2 && path[1] == ':')
#if defined(_WIN32) && !defined(UNDER_CE)
if (isRootPrefix && path.Len() == 2 && NName::IsDrivePath2(path))
{
// we use "c:" item as directory item
fi.Clear();
fi.ClearBase();
fi.Name = path;
fi.SetAsDir();
fi.Size = 0;
@@ -82,9 +94,12 @@ DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &r
resPath = path;
return error;
}
break;
}
bool found;
if (Enumerators.Back().Next(fi, found))
{
if (found)
@@ -101,18 +116,22 @@ DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &r
Prefixes.DeleteBack();
return error;
}
Enumerators.DeleteBack();
Prefixes.DeleteBack();
}
resPath += fi.Name;
if (EnterToDirs && fi.IsDir())
{
FString s = resPath;
s += FCHAR_PATH_SEPARATOR;
s.Add_PathSepar();
Prefixes.Add(s);
s += FCHAR_ANY_MASK;
Enumerators.Add(NFind::CEnumerator(BasePrefix + s));
}
filled = true;
return S_OK;
}
@@ -137,10 +156,9 @@ void CThreadCrc::AddErrorMessage(DWORD systemError, const FChar *name)
void CThreadCrc::SetStatus(const UString &s2)
{
UString s = s2;
if (Enumerator.BasePrefix)
if (!Enumerator.BasePrefix.IsEmpty())
{
if (!s.IsEmpty())
s += L' ';
s.Add_Space_if_NotEmpty();
s += fs2us(Enumerator.BasePrefix);
}
ProgressDialog.Sync.Set_Status(s);
@@ -201,10 +219,10 @@ HRESULT CThreadCrc::ProcessVirt()
*/
if (needPrint)
{
RINOK(sync.ScanProgress(numFiles, totalSize, fs2us(path), fi.IsDir()));
RINOK(sync.ScanProgress(numFiles, totalSize, path, fi.IsDir()));
}
}
RINOK(sync.ScanProgress(numFiles, totalSize, L"", false));
RINOK(sync.ScanProgress(numFiles, totalSize, FString(), false));
// sync.SetNumFilesTotal(numFiles);
// sync.SetProgress(totalSize, 0);
// SetStatus(LangString(IDS_CHECKSUM_CALCULATING));
@@ -235,7 +253,7 @@ HRESULT CThreadCrc::ProcessVirt()
if (!fi.IsDir())
{
NIO::CInFile inFile;
tempPath = Enumerator.BasePrefix;
tempPath = Enumerator.BasePrefix_for_Open;
tempPath += path;
if (!inFile.Open(tempPath))
{
@@ -289,13 +307,8 @@ HRESULT CThreadCrc::ProcessVirt()
return S_OK;
}
static void ThrowException_if_Error(HRESULT res)
{
if (res != S_OK)
throw CSystemException(res);
}
void CApp::CalculateCrc(const UString &methodName)
HRESULT CApp::CalculateCrc2(const UString &methodName)
{
int srcPanelIndex = GetFocusedPanelIndex();
CPanel &srcPanel = Panels[srcPanelIndex];
@@ -303,9 +316,9 @@ void CApp::CalculateCrc(const UString &methodName)
CRecordVector<UInt32> indices;
srcPanel.GetOperatedIndicesSmart(indices);
if (indices.IsEmpty())
return;
return S_OK;
if (!srcPanel.IsFsOrDrivesFolder())
if (!srcPanel.Is_IO_FS_Folder())
{
CCopyToOptions options;
options.streamMode = true;
@@ -313,27 +326,13 @@ void CApp::CalculateCrc(const UString &methodName)
options.hashMethods.Add(methodName);
UStringVector messages;
HRESULT res = srcPanel.CopyTo(options, indices, &messages);
if (res != S_OK)
{
if (res != E_ABORT)
srcPanel.MessageBoxError(res);
}
return;
return srcPanel.CopyTo(options, indices, &messages);
}
CCodecs *codecs = new CCodecs;
#ifdef EXTERNAL_CODECS
CExternalCodecs __externalCodecs;
__externalCodecs.GetCodecs = codecs;
__externalCodecs.GetHashers = codecs;
#else
CMyComPtr<IUnknown> compressCodecsInfo = codecs;
#endif
ThrowException_if_Error(codecs->Load());
#ifdef EXTERNAL_CODECS
ThrowException_if_Error(__externalCodecs.LoadCodecs());
LoadGlobalCodecs();
#endif
{
@@ -341,11 +340,23 @@ void CApp::CalculateCrc(const UString &methodName)
{
UStringVector methods;
methods.Add(methodName);
t.Hash.SetMethods(EXTERNAL_CODECS_VARS methods);
RINOK(t.Hash.SetMethods(EXTERNAL_CODECS_VARS_G methods));
}
FOR_VECTOR (i, indices)
t.Enumerator.FilePaths.Add(us2fs(srcPanel.GetItemRelPath(indices[i])));
t.Enumerator.BasePrefix = us2fs(srcPanel.GetFsPath());
UString basePrefix = srcPanel.GetFsPath();
UString basePrefix2 = basePrefix;
if (basePrefix2.Back() == ':')
{
int pos = basePrefix2.ReverseFind_PathSepar();
if (pos >= 0)
basePrefix2.DeleteFrom(pos + 1);
}
t.Enumerator.BasePrefix = us2fs(basePrefix);
t.Enumerator.BasePrefix_for_Open = us2fs(basePrefix2);
t.Enumerator.EnterToDirs = !GetFlatMode();
t.ProgressDialog.ShowCompressionInfo = false;
@@ -354,10 +365,22 @@ void CApp::CalculateCrc(const UString &methodName)
t.ProgressDialog.MainWindow = _window;
t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE);
t.ProgressDialog.MainAddTitle = title + UString(L' ');
t.ProgressDialog.MainAddTitle = title;
t.ProgressDialog.MainAddTitle.Add_Space();
if (t.Create(title, _window) != S_OK)
return;
RINOK(t.Create(title, _window));
}
RefreshTitleAlways();
return S_OK;
}
void CApp::CalculateCrc(const UString &methodName)
{
HRESULT res = CalculateCrc2(methodName);
if (res != S_OK && res != E_ABORT)
{
int srcPanelIndex = GetFocusedPanelIndex();
CPanel &srcPanel = Panels[srcPanelIndex];
srcPanel.MessageBoxError(res);
}
}

View File

@@ -296,9 +296,11 @@ static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &na
void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
{
CDisableTimerProcessing disableTimerProcessing2(*this);
if (!DoesItSupportOperations())
return;
CDisableTimerProcessing disableTimerProcessing2(*this);
CRecordVector<UInt32> indices;
GetOperatedItemIndices(indices);
if (indices.Size() == 0)
@@ -312,7 +314,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
bool isFSFolder = IsFSFolder();
if (isFSFolder)
dirPrefix = us2fs(_currentFolderPrefix);
dirPrefix = us2fs(GetFsPath());
else
{
tempDirectory.Create(kTempDirPrefix);
@@ -580,7 +582,9 @@ bool CDropTarget::IsItSameDrive() const
return false;
if (!IsFsFolderPath())
return false;
UString drive;
if (m_Panel->IsFSFolder())
{
drive = m_Panel->GetDriveOrNetworkPrefix();
@@ -594,13 +598,14 @@ bool CDropTarget::IsItSameDrive() const
if (m_SourcePaths.Size() == 0)
return false;
FOR_VECTOR (i, m_SourcePaths)
{
if (MyStringCompareNoCase_N(m_SourcePaths[i], drive, drive.Len()) != 0)
if (!m_SourcePaths[i].IsPrefixedBy_NoCase(drive))
return false;
}
return true;
}
DWORD CDropTarget::GetEffect(DWORD keyState, POINTL /* pt */, DWORD allowedEffect)
@@ -635,13 +640,11 @@ UString CDropTarget::GetTargetPath() const
{
if (!IsFsFolderPath())
return UString();
UString path = m_Panel->_currentFolderPrefix;
if (m_Panel->IsFSDrivesFolder())
path.Empty();
UString path = m_Panel->GetFsPath();
if (m_SubFolderIndex >= 0 && !m_SubFolderName.IsEmpty())
{
path += m_SubFolderName;
path += WCHAR_PATH_SEPARATOR;
path.Add_PathSepar();
}
return path;
}
@@ -728,7 +731,7 @@ STDMETHODIMP CDropTarget::Drop(IDataObject *dataObject, DWORD keyState,
UString path = GetTargetPath();
if (m_IsAppTarget && m_Panel)
if (m_Panel->IsFSFolder())
path = m_Panel->_currentFolderPrefix;
path = m_Panel->GetFsPath();
m_Panel->DropObject(dataObject, path);
}
}
@@ -779,7 +782,7 @@ static bool AreThereNamesFromTemp(const UStringVector &fileNames)
if (tempPath.IsEmpty())
return false;
FOR_VECTOR (i, fileNames)
if (MyStringCompareNoCase_N(fileNames[i], tempPath, tempPath.Len()) == 0)
if (fileNames[i].IsPrefixedBy_NoCase(tempPath))
return true;
return false;
}

View File

@@ -28,10 +28,38 @@ using namespace NWindows;
using namespace NFile;
using namespace NFind;
void CPanel::ReleaseFolder()
{
_folder.Release();
_folderCompare.Release();
_folderGetItemName.Release();
_folderRawProps.Release();
_folderAltStreams.Release();
_folderOperations.Release();
_thereAreDeletedItems = false;
}
void CPanel::SetNewFolder(IFolderFolder *newFolder)
{
ReleaseFolder();
_folder = newFolder;
if (_folder)
{
_folder.QueryInterface(IID_IFolderCompare, &_folderCompare);
_folder.QueryInterface(IID_IFolderGetItemName, &_folderGetItemName);
_folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps);
_folder.QueryInterface(IID_IFolderAltStreams, &_folderAltStreams);
_folder.QueryInterface(IID_IFolderOperations, &_folderOperations);
}
}
void CPanel::SetToRootFolder()
{
ReleaseFolder();
_library.Free();
CRootFolder *rootFolderSpec = new CRootFolder;
SetNewFolder(rootFolderSpec);
rootFolderSpec->Init();
@@ -39,105 +67,188 @@ void CPanel::SetToRootFolder()
HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted)
{
UString path = fullPath;
#ifdef _WIN32
path.Replace(L'/', WCHAR_PATH_SEPARATOR);
#endif
archiveIsOpened = false;
encrypted = false;
CDisableTimerProcessing disableTimerProcessing(*this);
CDisableNotify disableNotify(*this);
if (_parentFolders.Size() > 0)
for (; !_parentFolders.IsEmpty(); CloseOneLevel())
{
const UString &virtPath = _parentFolders.Back().VirtualPath;
if (fullPath.IsPrefixedBy(virtPath))
// ---------- we try to use open archive ----------
const CFolderLink &link = _parentFolders.Back();
const UString &virtPath = link.VirtualPath;
if (!path.IsPrefixedBy(virtPath))
continue;
UString relatPath = path.Ptr(virtPath.Len());
if (!relatPath.IsEmpty())
{
for (;;)
if (!IS_PATH_SEPAR(relatPath[0]))
continue;
else
relatPath.Delete(0);
}
UString relatPath2 = relatPath;
if (!relatPath2.IsEmpty() && !IS_PATH_SEPAR(relatPath2.Back()))
relatPath2.Add_PathSepar();
for (;;)
{
const UString foldPath = GetFolderPath(_folder);
if (relatPath2 == foldPath)
break;
if (relatPath.IsPrefixedBy(foldPath))
{
CMyComPtr<IFolderFolder> newFolder;
HRESULT res = _folder->BindToParentFolder(&newFolder);
if (!newFolder || res != S_OK)
break;
SetNewFolder(newFolder);
path = relatPath.Ptr(foldPath.Len());
break;
}
UStringVector parts;
SplitPathToParts(fullPath.Ptr(virtPath.Len()), parts);
FOR_VECTOR (i, parts)
CMyComPtr<IFolderFolder> newFolder;
if (_folder->BindToParentFolder(&newFolder) != S_OK)
throw 20140918;
if (!newFolder) // we exit from loop above if (relatPath.IsPrefixedBy(empty path for root folder)
throw 20140918;
SetNewFolder(newFolder);
}
break;
}
if (_parentFolders.IsEmpty())
{
// ---------- we open file or folder from file system ----------
CloseOpenFolders();
UString sysPath = path;
unsigned prefixSize = NName::GetRootPrefixSize(sysPath);
if (prefixSize == 0 || sysPath[prefixSize] == 0)
sysPath.Empty();
#if defined(_WIN32) && !defined(UNDER_CE)
if (!sysPath.IsEmpty() && sysPath.Back() == ':' &&
(sysPath.Len() != 2 || !NName::IsDrivePath2(sysPath)))
{
UString baseFile = sysPath;
baseFile.DeleteBack();
if (NFind::DoesFileOrDirExist(us2fs(baseFile)))
sysPath.Empty();
}
#endif
CFileInfo fileInfo;
while (!sysPath.IsEmpty())
{
if (fileInfo.Find(us2fs(sysPath)))
break;
int pos = sysPath.ReverseFind_PathSepar();
if (pos < 0)
sysPath.Empty();
else
{
const UString &s = parts[i];
if ((i == 0 || i == parts.Size() - 1) && s.IsEmpty())
continue;
CMyComPtr<IFolderFolder> newFolder;
HRESULT res = _folder->BindToFolder(s, &newFolder);
if (!newFolder || res != S_OK)
break;
SetNewFolder(newFolder);
/*
if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1)
reducedParts.Add(sysPath.Ptr(pos + 1));
*/
#if defined(_WIN32) && !defined(UNDER_CE)
if (pos == 2 && NName::IsDrivePath2(sysPath) && sysPath.Len() > 3)
pos++;
#endif
sysPath.DeleteFrom(pos);
}
}
SetToRootFolder();
CMyComPtr<IFolderFolder> newFolder;
if (sysPath.IsEmpty())
{
_folder->BindToFolder(path, &newFolder);
}
else if (fileInfo.IsDir())
{
NName::NormalizeDirPathPrefix(sysPath);
_folder->BindToFolder(sysPath, &newFolder);
}
else
{
FString dirPrefix, fileName;
NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName);
HRESULT res;
// = OpenItemAsArchive(fs2us(fileName), arcFormat, encrypted);
{
CTempFileInfo tfi;
tfi.RelPath = fs2us(fileName);
tfi.FolderPath = dirPrefix;
tfi.FilePath = us2fs(sysPath);
res = OpenItemAsArchive(NULL, tfi, sysPath, arcFormat, encrypted);
}
if (res == S_FALSE)
_folder->BindToFolder(fs2us(dirPrefix), &newFolder);
else
{
RINOK(res);
archiveIsOpened = true;
_parentFolders.Back().ParentFolderPath = fs2us(dirPrefix);
path.DeleteFrontal(sysPath.Len());
if (!path.IsEmpty() && IS_PATH_SEPAR(path[0]))
path.Delete(0);
}
}
if (newFolder)
{
SetNewFolder(newFolder);
// LoadFullPath();
return S_OK;
}
}
{
// ---------- we open folder remPath in archive and sub archives ----------
CloseOpenFolders();
UString sysPath = fullPath;
CFileInfo fileInfo;
UStringVector reducedParts;
while (!sysPath.IsEmpty())
{
if (fileInfo.Find(us2fs(sysPath)))
break;
int pos = sysPath.ReverseFind(WCHAR_PATH_SEPARATOR);
if (pos < 0)
sysPath.Empty();
else
for (unsigned curPos = 0; curPos != path.Len();)
{
if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1)
reducedParts.Add(sysPath.Ptr(pos + 1));
sysPath.DeleteFrom(pos);
}
}
SetToRootFolder();
CMyComPtr<IFolderFolder> newFolder;
if (sysPath.IsEmpty())
{
if (_folder->BindToFolder(fullPath, &newFolder) == S_OK)
SetNewFolder(newFolder);
}
else if (fileInfo.IsDir())
{
NName::NormalizeDirPathPrefix(sysPath);
if (_folder->BindToFolder(sysPath, &newFolder) == S_OK)
SetNewFolder(newFolder);
}
else
{
FString dirPrefix, fileName;
NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName);
if (_folder->BindToFolder(fs2us(dirPrefix), &newFolder) == S_OK)
{
SetNewFolder(newFolder);
LoadFullPath();
UString s = path.Ptr(curPos);
int slashPos = NName::FindSepar(s);
unsigned skipLen = s.Len();
if (slashPos >= 0)
{
HRESULT res = OpenItemAsArchive(fs2us(fileName), arcFormat, encrypted);
if (res != S_FALSE)
s.DeleteFrom(slashPos);
skipLen = slashPos + 1;
}
CMyComPtr<IFolderFolder> newFolder;
_folder->BindToFolder(s, &newFolder);
if (newFolder)
curPos += skipLen;
else if (_folderAltStreams)
{
int pos = s.Find(L':');
if (pos >= 0)
{
RINOK(res);
}
/*
if (res == E_ABORT)
return res;
*/
if (res == S_OK)
{
archiveIsOpened = true;
for (int i = reducedParts.Size() - 1; i >= 0; i--)
{
CMyComPtr<IFolderFolder> newFolder;
_folder->BindToFolder(reducedParts[i], &newFolder);
if (!newFolder)
break;
SetNewFolder(newFolder);
}
UString baseName = s;
baseName.DeleteFrom(pos);
if (_folderAltStreams->BindToAltStreams(baseName, &newFolder) == S_OK && newFolder)
curPos += pos + 1;
}
}
if (!newFolder)
break;
SetNewFolder(newFolder);
}
}
return S_OK;
}
@@ -163,10 +274,12 @@ void CPanel::OpenBookmark(int index)
UString GetFolderPath(IFolderFolder *folder)
{
NCOM::CPropVariant prop;
if (folder->GetFolderProperty(kpidPath, &prop) == S_OK)
if (prop.vt == VT_BSTR)
return (wchar_t *)prop.bstrVal;
{
NCOM::CPropVariant prop;
if (folder->GetFolderProperty(kpidPath, &prop) == S_OK)
if (prop.vt == VT_BSTR)
return (wchar_t *)prop.bstrVal;
}
return UString();
}
@@ -176,9 +289,10 @@ void CPanel::LoadFullPath()
FOR_VECTOR (i, _parentFolders)
{
const CFolderLink &folderLink = _parentFolders[i];
_currentFolderPrefix += GetFolderPath(folderLink.ParentFolder);
_currentFolderPrefix += folderLink.ParentFolderPath;
// GetFolderPath(folderLink.ParentFolder);
_currentFolderPrefix += folderLink.RelPath;
_currentFolderPrefix += WCHAR_PATH_SEPARATOR;
_currentFolderPrefix.Add_PathSepar();
}
if (_folder)
_currentFolderPrefix += GetFolderPath(_folder);
@@ -364,7 +478,7 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
{
UString name = pathParts[i];
sumPass += name;
sumPass += WCHAR_PATH_SEPARATOR;
sumPass.Add_PathSepar();
CFileInfo info;
DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
if (info.Find(us2fs(sumPass)))
@@ -496,73 +610,104 @@ void CPanel::FoldersHistory()
void CPanel::OpenParentFolder()
{
LoadFullPath(); // Maybe we don't need it ??
UString focucedName;
if (!_currentFolderPrefix.IsEmpty() &&
_currentFolderPrefix.Back() == WCHAR_PATH_SEPARATOR)
UString parentFolderPrefix;
UString focusedName;
if (!_currentFolderPrefix.IsEmpty())
{
focucedName = _currentFolderPrefix;
focucedName.DeleteBack();
if (focucedName != L"\\\\.")
wchar_t c = _currentFolderPrefix.Back();
if (c == WCHAR_PATH_SEPARATOR || c == ':')
{
int pos = focucedName.ReverseFind(WCHAR_PATH_SEPARATOR);
if (pos >= 0)
focucedName.DeleteFrontal(pos + 1);
focusedName = _currentFolderPrefix;
focusedName.DeleteBack();
/*
if (c == ':' && !focusedName.IsEmpty() && focusedName.Back() == WCHAR_PATH_SEPARATOR)
{
focusedName.DeleteBack();
}
else
*/
if (focusedName != L"\\\\." &&
focusedName != L"\\\\?")
{
int pos = focusedName.ReverseFind_PathSepar();
if (pos >= 0)
{
parentFolderPrefix = focusedName;
parentFolderPrefix.DeleteFrom(pos + 1);
focusedName.DeleteFrontal(pos + 1);
}
}
}
}
CDisableTimerProcessing disableTimerProcessing(*this);
CDisableNotify disableNotify(*this);
CMyComPtr<IFolderFolder> newFolder;
_folder->BindToParentFolder(&newFolder);
// newFolder.Release(); // for test
if (newFolder)
SetNewFolder(newFolder);
else
{
if (_parentFolders.IsEmpty())
bool needSetFolder = true;
if (!_parentFolders.IsEmpty())
{
SetToRootFolder();
if (focucedName.IsEmpty())
focucedName = GetItemName(0);
{
const CFolderLink &link = _parentFolders.Back();
parentFolderPrefix = link.ParentFolderPath;
focusedName = link.RelPath;
}
CloseOneLevel();
needSetFolder = (!_folder);
}
else
if (needSetFolder)
{
ReleaseFolder();
_library.Free();
CFolderLink &link = _parentFolders.Back();
SetNewFolder(link.ParentFolder);
_library.Attach(link.Library.Detach());
focucedName = link.RelPath;
if (_parentFolders.Size() > 1)
OpenParentArchiveFolder();
_parentFolders.DeleteBack();
if (_parentFolders.IsEmpty())
_flatMode = _flatModeForDisk;
{
bool archiveIsOpened;
bool encrypted;
BindToPath(parentFolderPrefix, UString(), archiveIsOpened, encrypted);
}
}
}
UStringVector selectedItems;
/*
if (!focucedName.IsEmpty())
selectedItems.Add(focucedName);
if (!focusedName.IsEmpty())
selectedItems.Add(focusedName);
*/
LoadFullPath();
// ::SetCurrentDirectory(::_currentFolderPrefix);
RefreshListCtrl(focucedName, -1, true, selectedItems);
RefreshListCtrl(focusedName, -1, true, selectedItems);
// _listView.EnsureVisible(_listView.GetFocusedItem(), false);
}
void CPanel::CloseOneLevel()
{
ReleaseFolder();
_library.Free();
{
CFolderLink &link = _parentFolders.Back();
if (link.ParentFolder)
SetNewFolder(link.ParentFolder);
_library.Attach(link.Library.Detach());
}
if (_parentFolders.Size() > 1)
OpenParentArchiveFolder();
_parentFolders.DeleteBack();
if (_parentFolders.IsEmpty())
_flatMode = _flatModeForDisk;
}
void CPanel::CloseOpenFolders()
{
while (_parentFolders.Size() > 0)
{
ReleaseFolder();
_library.Free();
SetNewFolder(_parentFolders.Back().ParentFolder);
_library.Attach(_parentFolders.Back().Library.Detach());
if (_parentFolders.Size() > 1)
OpenParentArchiveFolder();
_parentFolders.DeleteBack();
}
while (!_parentFolders.IsEmpty())
CloseOneLevel();
_flatMode = _flatModeForDisk;
ReleaseFolder();
_library.Free();
@@ -618,3 +763,45 @@ void CPanel::OpenFolder(int index)
_listView.SetItemState_Selected(_listView.GetFocusedItem());
_listView.EnsureVisible(_listView.GetFocusedItem(), false);
}
void CPanel::OpenAltStreams()
{
CRecordVector<UInt32> indices;
GetOperatedItemIndices(indices);
Int32 realIndex = -1;
if (indices.Size() > 1)
return;
if (indices.Size() == 1)
realIndex = indices[0];
if (_folderAltStreams)
{
CMyComPtr<IFolderFolder> newFolder;
_folderAltStreams->BindToAltStreams(realIndex, &newFolder);
if (newFolder)
{
CDisableTimerProcessing disableTimerProcessing(*this);
CDisableNotify disableNotify(*this);
SetNewFolder(newFolder);
RefreshListCtrl(UString(), -1, true, UStringVector());
return;
}
return;
}
#if defined(_WIN32) && !defined(UNDER_CE)
UString path;
if (realIndex >= 0)
path = GetItemFullPath(realIndex);
else
{
path = GetFsPath();
if (!NName::IsDriveRootPath_SuperAllowed(us2fs(path)))
if (!path.IsEmpty() && IS_PATH_SEPAR(path.Back()))
path.DeleteBack();
}
path += L':';
BindToPathAndRefresh(path);
#endif
}

View File

@@ -157,7 +157,8 @@ public:
static bool IsNameVirus(const UString &name)
{
return (name.Find(L" ") >= 0);
// return (name.Find(L" ") >= 0);
return (wcsstr(name, L" ") != NULL);
}
struct CTmpProcessInfo: public CTempFileInfo
@@ -223,7 +224,13 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream,
folderLink.Password = password;
folderLink.UsePassword = encrypted;
folderLink.ParentFolder = _folder;
if (_folder)
folderLink.ParentFolderPath = GetFolderPath(_folder);
else
folderLink.ParentFolderPath = _currentFolderPrefix;
if (!_parentFolders.IsEmpty())
folderLink.ParentFolder = _folder;
_parentFolders.Add(folderLink);
_parentFolders.Back().Library.Attach(_library.Detach());
@@ -272,7 +279,7 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream,
if (!values[0].IsEmpty())
{
if (!s2.IsEmpty())
s2 += L"\n";
s2.Add_LF();
s2 += L"[";
s2 += values[2];
s2 += L"] Error: ";
@@ -283,7 +290,7 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream,
if (!s.IsEmpty())
s += L"--------------------\n";
s += values[1];
s += L"\n";
s.Add_LF();
s += s2;
}
}
@@ -305,8 +312,8 @@ HRESULT CPanel::OpenItemAsArchive(const UString &relPath, const UString &arcForm
{
CTempFileInfo tfi;
tfi.RelPath = relPath;
tfi.FolderPath = us2fs(_currentFolderPrefix);
const UString fullPath = _currentFolderPrefix + relPath;
tfi.FolderPath = us2fs(GetFsPath());
const UString fullPath = GetFsPath() + relPath;
tfi.FilePath = us2fs(fullPath);
return OpenItemAsArchive(NULL, tfi, fullPath, arcFormat, encrypted);
}
@@ -316,7 +323,7 @@ HRESULT CPanel::OpenItemAsArchive(int index)
CDisableTimerProcessing disableTimerProcessing1(*this);
CDisableNotify disableNotify(*this);
bool encrypted;
HRESULT res = OpenItemAsArchive(GetItemRelPath(index), UString(), encrypted);
HRESULT res = OpenItemAsArchive(GetItemRelPath2(index), UString(), encrypted);
if (res != S_OK)
{
RefreshTitle(true); // in case of error we must refresh changed title of 7zFM
@@ -379,7 +386,7 @@ static const char *kStartExtensions =
static bool FindExt(const char *p, const UString &name)
{
int dotPos = name.ReverseFind('.');
int dotPos = name.ReverseFind_Dot();
if (dotPos < 0 || dotPos == (int)name.Len() - 1)
return false;
@@ -409,10 +416,7 @@ static bool DoItemAlwaysStart(const UString &name)
return FindExt(kStartExtensions, name);
}
static UString GetQuotedString(const UString &s)
{
return UString(L'\"') + s + UString(L'\"');
}
UString GetQuotedString(const UString &s);
static HRESULT StartEditApplication(const UString &path, bool useEditor, HWND window, CProcess &process)
{
@@ -455,13 +459,17 @@ void CApp::DiffFiles()
{
const CPanel &destPanel = Panels[1 - LastFocusedPanel];
path1 = panel.GetItemFullPath(indices[0]);
const UString relPath = panel.GetItemRelPath(indices[0]);
CRecordVector<UInt32> indices2;
destPanel.GetSelectedItemsIndices(indices2);
if (indices2.Size() == 1)
path2 = destPanel.GetItemFullPath(indices2[0]);
else
{
UString relPath = panel.GetItemRelPath2(indices[0]);
if (panel._flatMode && !destPanel._flatMode)
relPath = panel.GetItemName(indices[0]);
path2 = destPanel._currentFolderPrefix + relPath;
}
}
else
return;
@@ -471,7 +479,9 @@ void CApp::DiffFiles()
if (command.IsEmpty())
return;
UString param = GetQuotedString(path1) + L' ' + GetQuotedString(path2);
UString param = GetQuotedString(path1);
param.Add_Space();
param += GetQuotedString(path2);
HRESULT res = MyCreateProcess(command, param);
if (res == SZ_OK)
@@ -573,11 +583,11 @@ void CPanel::OpenFolderExternal(int index)
UString name;
if (index == kParentIndex)
{
int pos = fsPrefix.ReverseFind(WCHAR_PATH_SEPARATOR);
int pos = fsPrefix.ReverseFind_PathSepar();
if (pos >= 0 && pos == (int)fsPrefix.Len() - 1)
{
UString s = fsPrefix.Left(pos);
pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);
pos = s.ReverseFind_PathSepar();
if (pos >= 0)
fsPrefix.SetFrom(s, pos + 1);
}
@@ -591,7 +601,7 @@ void CPanel::OpenFolderExternal(int index)
void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal)
{
CDisableTimerProcessing disableTimerProcessing(*this);
UString name = GetItemRelPath(index);
UString name = GetItemRelPath2(index);
if (IsNameVirus(name))
{
MessageBoxErrorLang(IDS_VIRUS);
@@ -650,8 +660,7 @@ HRESULT CThreadCopyFrom::ProcessVirt()
HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath,
bool usePassword, const UString &password)
{
CMyComPtr<IFolderOperations> folderOperations;
if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
if (!_folderOperations)
{
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return E_FAIL;
@@ -663,8 +672,13 @@ HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath,
t.UpdateCallbackSpec->ProgressDialog = &t.ProgressDialog;
t.ItemIndex = index;
t.FullPath = fullFilePath;
t.FolderOperations = folderOperations;
t.UpdateCallbackSpec->Init(usePassword, password);
t.FolderOperations = _folderOperations;
t.UpdateCallbackSpec->Init();
t.UpdateCallbackSpec->PasswordIsDefined = usePassword;
t.UpdateCallbackSpec->Password = password;
RINOK(t.Create(GetItemName(index), (HWND)*this));
return t.Result;
}
@@ -862,8 +876,11 @@ STDMETHODIMP CBufSeqOutStream_WithFile::Write(const void *data, UInt32 size, UIn
{
if (_size - _pos >= size)
{
memcpy(_buffer + _pos, data, size);
_pos += size;
if (size != 0)
{
memcpy(_buffer + _pos, data, size);
_pos += size;
}
if (processedSize)
*processedSize = (UInt32)size;
return S_OK;
@@ -931,8 +948,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
return;
}
CMyComPtr<IFolderOperations> folderOperations;
if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
if (!_folderOperations)
{
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
@@ -951,7 +967,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
FString tempDir = tempDirectory.GetPath();
FString tempDirNorm = tempDir;
NName::NormalizeDirPathPrefix(tempDirNorm);
const FString tempFilePath = tempDirNorm + us2fs(GetCorrectFsPath(name));
const FString tempFilePath = tempDirNorm + us2fs(Get_Correct_FsFile_Name(name));
CTempFileInfo tempFileInfo;
tempFileInfo.FileIndex = index;
@@ -1029,7 +1045,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
bool isAltStream = IsItem_AltStream(index);
CCopyToOptions options;
options.includeAltStreams = false;
options.includeAltStreams = true;
options.replaceAltStreamChars = isAltStream;
if (tryAsArchive)
@@ -1137,11 +1153,11 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
return;
CProcess process;
/* HRESULT res; */
// HRESULT res;
if (editMode)
/* res = */ StartEditApplication(fs2us(tempFilePath), useEditor, (HWND)*this, process);
else
/* res = */ StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process);
/* res = */ StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process);
if ((HANDLE)process == 0)
return;

View File

@@ -4,6 +4,7 @@
#include "../../../../C/Sort.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/Menu.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/PropVariantConv.h"
@@ -103,7 +104,7 @@ HRESULT CPanel::InitColumns()
_properties.Clear();
_needSaveInfo = true;
bool isFsFolder = IsFSFolder();
bool isFsFolder = IsFSFolder() || IsAltStreamsFolder();
{
UInt32 numProps;
@@ -401,7 +402,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
int cursorIndex = -1;
CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
if (!IsFSFolder() || _showRealFileIcons)
if (!Is_Slow_Icon_Folder() || _showRealFileIcons)
_folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);
if (!IsFSFolder())
@@ -436,7 +437,8 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
int subItem = 0;
item.iSubItem = subItem++;
item.lParam = kParentIndex;
item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);
// item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);
item.pszText = LPSTR_TEXTCALLBACKW;
UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY;
item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);
if (item.iImage < 0)
@@ -451,19 +453,23 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
UString correctedName;
UString itemName;
UString relPath;
for (UInt32 i = 0; i < numItems; i++)
{
const wchar_t *name = NULL;
unsigned nameLen = 0;
if (_folderGetItemName)
_folderGetItemName->GetItemName(i, &name, &nameLen);
if (name == NULL)
if (!name)
{
GetItemNameFast(i, itemName);
GetItemName(i, itemName);
name = itemName;
nameLen = itemName.Len();
}
bool selected = false;
if (!focusedName.IsEmpty() || !selectedNames.IsEmpty())
{
relPath.Empty();
@@ -495,6 +501,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
if (selectedNames.FindInSorted(relPath) >= 0)
selected = true;
}
_selectedStatusVector.AddInReserved(selected);
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
@@ -567,6 +574,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
// }
bool defined = false;
if (folderGetSystemIconIndex)
{
folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);
@@ -585,6 +593,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
item.iImage = _extToIconMap.GetIconIndex(attrib, name);
}
}
if (item.iImage < 0)
item.iImage = 0;
@@ -592,6 +601,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
return E_FAIL;
listViewItemCount++;
}
// OutputDebugStringA("End2\n");
if (_listView.GetItemCount() > 0 && cursorIndex >= 0)
@@ -831,7 +841,24 @@ UString CPanel::GetItemName(int itemIndex) const
return prop.bstrVal;
}
void CPanel::GetItemNameFast(int itemIndex, UString &s) const
UString CPanel::GetItemName_for_Copy(int itemIndex) const
{
if (itemIndex == kParentIndex)
return L"..";
{
NCOM::CPropVariant prop;
if (_folder->GetProperty(itemIndex, kpidOutName, &prop) == S_OK)
{
if (prop.vt == VT_BSTR)
return prop.bstrVal;
if (prop.vt != VT_EMPTY)
throw 2723401;
}
}
return GetItemName(itemIndex);
}
void CPanel::GetItemName(int itemIndex, UString &s) const
{
if (itemIndex == kParentIndex)
{
@@ -843,8 +870,7 @@ void CPanel::GetItemNameFast(int itemIndex, UString &s) const
throw 2723400;
if (prop.vt != VT_BSTR)
throw 2723401;
s.Empty();
s += prop.bstrVal;
s.SetFromBstr(prop.bstrVal);
}
UString CPanel::GetItemPrefix(int itemIndex) const
@@ -856,7 +882,7 @@ UString CPanel::GetItemPrefix(int itemIndex) const
throw 2723400;
UString prefix;
if (prop.vt == VT_BSTR)
prefix = prop.bstrVal;
prefix.SetFromBstr(prop.bstrVal);
return prefix;
}
@@ -865,9 +891,22 @@ UString CPanel::GetItemRelPath(int itemIndex) const
return GetItemPrefix(itemIndex) + GetItemName(itemIndex);
}
UString CPanel::GetItemRelPath2(int itemIndex) const
{
UString s = GetItemRelPath(itemIndex);
#if defined(_WIN32) && !defined(UNDER_CE)
if (s.Len() == 2 && NFile::NName::IsDrivePath2(s))
{
if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix())
s.Add_PathSepar();
}
#endif
return s;
}
UString CPanel::GetItemFullPath(int itemIndex) const
{
return _currentFolderPrefix + GetItemRelPath(itemIndex);
return GetFsPath() + GetItemRelPath2(itemIndex);
}
bool CPanel::GetItem_BoolProp(UInt32 itemIndex, PROPID propID) const
@@ -928,6 +967,7 @@ void CPanel::ReadListViewInfo()
void CPanel::SaveListViewInfo()
{
unsigned i;
for (i = 0; i < _visibleProperties.Size(); i++)
{
CItemProperty &prop = _visibleProperties[i];
@@ -945,6 +985,7 @@ void CPanel::SaveListViewInfo()
PROPID sortPropID = _sortID;
_visibleProperties.Sort();
for (i = 0; i < _visibleProperties.Size(); i++)
{
const CItemProperty &prop = _visibleProperties[i];
@@ -954,6 +995,7 @@ void CPanel::SaveListViewInfo()
columnInfo.Width = prop.Width;
viewInfo.Columns.Add(columnInfo);
}
for (i = 0; i < _properties.Size(); i++)
{
const CItemProperty &prop = _properties[i];
@@ -1025,21 +1067,24 @@ void CPanel::ShowColumnsContextMenu(int x, int y)
else
{
int visibleIndex = _visibleProperties.FindItemWithID(prop.ID);
_visibleProperties.Delete(visibleIndex);
/*
if (_sortIndex == index)
if (visibleIndex >= 0)
{
_visibleProperties.Delete(visibleIndex);
/*
if (_sortIndex == index)
{
_sortIndex = 0;
_ascending = true;
}
*/
if (_sortID == prop.ID)
{
_sortID = kpidName;
_ascending = true;
}
_listView.DeleteColumn(visibleIndex);
}
*/
if (_sortID == prop.ID)
{
_sortID = kpidName;
_ascending = true;
}
_listView.DeleteColumn(visibleIndex);
}
}
}

View File

@@ -19,30 +19,57 @@
using namespace NWindows;
static void ConvertSizeToString(UInt64 value, wchar_t *dest)
{
char s[32];
ConvertUInt64ToString(value, s);
unsigned i = MyStringLen(s);
unsigned pos = ARRAY_SIZE(s);
s[--pos] = 0;
while (i > 3)
{
s[--pos] = s[--i];
s[--pos] = s[--i];
s[--pos] = s[--i];
s[--pos] = L' ';
}
while (i > 0)
s[--pos] = s[--i];
#define INT_TO_STR_SPEC(v) \
while (v >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(v % 10)); v /= 10; } \
*s++ = (unsigned char)('0' + (unsigned)v);
for (;;)
static void ConvertSizeToString(UInt64 val, wchar_t *s) throw()
{
unsigned char temp[32];
unsigned i = 0;
if (val <= (UInt32)0xFFFFFFFF)
{
char c = s[pos++];
*dest++ = (unsigned char)c;
if (c == 0)
break;
UInt32 val32 = (UInt32)val;
INT_TO_STR_SPEC(val32)
}
else
{
INT_TO_STR_SPEC(val)
}
if (i < 3)
{
if (i != 0)
{
*s++ = temp[i - 1];
if (i == 2)
*s++ = temp[0];
}
*s = 0;
return;
}
unsigned r = i % 3;
if (r != 0)
{
s[0] = temp[--i];
if (r == 2)
s[1] = temp[--i];
s += r;
}
do
{
s[0] = ' ';
s[1] = temp[i - 1];
s[2] = temp[i - 2];
s[3] = temp[i - 3];
s += 4;
}
while (i -= 3);
*s = 0;
}
UString ConvertSizeToString(UInt64 value)
@@ -52,29 +79,62 @@ UString ConvertSizeToString(UInt64 value)
return s;
}
static inline char GetHex(Byte value)
static inline unsigned GetHex(unsigned v)
{
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
return (v < 10) ? ('0' + v) : ('A' + (v - 10));
}
void HexToString(char *dest, const Byte *data, UInt32 size)
/*
static void HexToString(char *dest, const Byte *data, UInt32 size)
{
for (UInt32 i = 0; i < size; i++)
{
Byte b = data[i];
dest[0] = GetHex((Byte)((b >> 4) & 0xF));
dest[1] = GetHex((Byte)(b & 0xF));
unsigned b = data[i];
dest[0] = GetHex((b >> 4) & 0xF);
dest[1] = GetHex(b & 0xF);
dest += 2;
}
*dest = 0;
}
*/
bool IsSizeProp(UINT propID) throw()
{
switch (propID)
{
case kpidSize:
case kpidPackSize:
case kpidNumSubDirs:
case kpidNumSubFiles:
case kpidOffset:
case kpidLinks:
case kpidNumBlocks:
case kpidNumVolumes:
case kpidPhySize:
case kpidHeadersSize:
case kpidTotalSize:
case kpidFreeSpace:
case kpidClusterSize:
case kpidNumErrors:
case kpidNumStreams:
case kpidNumAltStreams:
case kpidAltStreamsSize:
case kpidVirtualSize:
case kpidUnpackSize:
case kpidTotalPhySize:
case kpidTailSize:
case kpidEmbeddedStubSize:
return true;
}
return false;
}
LRESULT CPanel::SetItemText(LVITEMW &item)
{
if (_dontShowMode)
return 0;
UInt32 realIndex = GetRealIndex(item);
/*
if ((item.mask & LVIF_IMAGE) != 0)
{
@@ -107,10 +167,31 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
if ((item.mask & LVIF_TEXT) == 0)
return 0;
if (realIndex == kParentIndex)
LPWSTR text = item.pszText;
if (item.cchTextMax > 0)
text[0] = 0;
if (item.cchTextMax <= 1)
return 0;
const CItemProperty &property = _visibleProperties[item.iSubItem];
PROPID propID = property.ID;
if (realIndex == kParentIndex)
{
if (propID == kpidName)
{
if (item.cchTextMax > 2)
{
text[0] = '.';
text[1] = '.';
text[2] = 0;
}
}
return 0;
}
if (property.IsRawProp)
{
@@ -118,10 +199,10 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
UInt32 dataSize;
UInt32 propType;
RINOK(_folderRawProps->GetRawProp(realIndex, propID, &data, &dataSize, &propType));
int limit = item.cchTextMax - 1;
unsigned limit = item.cchTextMax - 1;
if (dataSize == 0)
{
item.pszText[0] = 0;
text[0] = 0;
return 0;
}
@@ -131,15 +212,15 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
ConvertNtReparseToString((const Byte *)data, dataSize, s);
if (!s.IsEmpty())
{
int i;
unsigned i;
for (i = 0; i < limit; i++)
{
wchar_t c = s[i];
if (c == 0)
break;
item.pszText[i] = c;
text[i] = c;
}
item.pszText[i] = 0;
text[i] = 0;
return 0;
}
}
@@ -149,45 +230,45 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
ConvertNtSecureToString((const Byte *)data, dataSize, s);
if (!s.IsEmpty())
{
int i;
unsigned i;
for (i = 0; i < limit; i++)
{
wchar_t c = s[i];
wchar_t c = (Byte)s[i];
if (c == 0)
break;
item.pszText[i] = c;
text[i] = c;
}
item.pszText[i] = 0;
text[i] = 0;
return 0;
}
}
{
const UInt32 kMaxDataSize = 64;
const unsigned kMaxDataSize = 64;
if (dataSize > kMaxDataSize)
{
char temp[64];
char temp[32];
MyStringCopy(temp, "data:");
ConvertUInt32ToString(dataSize, temp + 5);
int i;
unsigned i;
for (i = 0; i < limit; i++)
{
wchar_t c = temp[i];
wchar_t c = (Byte)temp[i];
if (c == 0)
break;
item.pszText[i] = c;
text[i] = c;
}
item.pszText[i] = 0;
text[i] = 0;
}
else
{
if ((int)dataSize > limit)
if (dataSize > limit)
dataSize = limit;
WCHAR *dest = item.pszText;
WCHAR *dest = text;
for (UInt32 i = 0; i < dataSize; i++)
{
Byte b = ((const Byte *)data)[i];
dest[0] = GetHex((Byte)((b >> 4) & 0xF));
dest[1] = GetHex((Byte)(b & 0xF));
unsigned b = ((const Byte *)data)[i];
dest[0] = (WCHAR)GetHex((b >> 4) & 0xF);
dest[1] = (WCHAR)GetHex(b & 0xF);
dest += 2;
}
*dest = 0;
@@ -230,11 +311,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
*/
if (item.cchTextMax < 32)
{
if (item.cchTextMax > 0)
item.pszText[0] = 0;
return 0;
}
if (propID == kpidName)
{
@@ -245,35 +322,36 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
_folderGetItemName->GetItemName(realIndex, &name, &nameLen);
if (name)
{
int dest = 0;
int limit = item.cchTextMax - 1;
for (int i = 0; dest < limit;)
unsigned dest = 0;
unsigned limit = item.cchTextMax - 1;
for (unsigned i = 0; dest < limit;)
{
wchar_t c = name[i++];
if (c == 0)
break;
item.pszText[dest++] = c;
text[dest++] = c;
if (c != ' ')
continue;
if (name[i + 1] != ' ')
continue;
int t = 2;
unsigned t = 2;
for (; name[i + t] == ' '; t++);
if (t >= 4 && dest + 4 <= limit)
{
item.pszText[dest++] = '.';
item.pszText[dest++] = '.';
item.pszText[dest++] = '.';
item.pszText[dest++] = ' ';
text[dest++] = '.';
text[dest++] = '.';
text[dest++] = '.';
text[dest++] = ' ';
i += t;
}
}
item.pszText[dest] = 0;
text[dest] = 0;
return 0;
}
}
}
if (propID == kpidPrefix)
{
if (_folderGetItemName)
@@ -283,73 +361,65 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
_folderGetItemName->GetItemPrefix(realIndex, &name, &nameLen);
if (name)
{
int dest = 0;
int limit = item.cchTextMax - 1;
for (int i = 0; dest < limit;)
unsigned dest = 0;
unsigned limit = item.cchTextMax - 1;
for (unsigned i = 0; dest < limit;)
{
wchar_t c = name[i++];
if (c == 0)
break;
item.pszText[dest++] = c;
text[dest++] = c;
}
item.pszText[dest] = 0;
text[dest] = 0;
return 0;
}
}
}
HRESULT res = _folder->GetProperty(realIndex, propID, &prop);
if (res != S_OK)
{
MyStringCopy(item.pszText, L"Error: ");
MyStringCopy(text, L"Error: ");
// s = UString(L"Error: ") + HResultToMessage(res);
}
else if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && (
propID == kpidSize ||
propID == kpidPackSize ||
propID == kpidNumSubDirs ||
propID == kpidNumSubFiles ||
propID == kpidPosition ||
propID == kpidNumBlocks ||
propID == kpidClusterSize ||
propID == kpidTotalSize ||
propID == kpidFreeSpace ||
propID == kpidUnpackSize
))
else if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID))
{
UInt64 v = 0;
ConvertPropVariantToUInt64(prop, v);
ConvertSizeToString(v, item.pszText);
ConvertSizeToString(v, text);
}
else if (prop.vt == VT_BSTR)
{
int limit = item.cchTextMax - 1;
unsigned limit = item.cchTextMax - 1;
const wchar_t *src = prop.bstrVal;
int i;
unsigned i;
for (i = 0; i < limit; i++)
{
wchar_t c = src[i];
if (c == 0) break;
if (c == 0xA) c = ' ';
if (c == 0xD) c = ' ';
item.pszText[i] = c;
text[i] = c;
}
item.pszText[i] = 0;
text[i] = 0;
}
else
{
char temp[64];
ConvertPropertyToShortString(temp, prop, propID, false);
int i;
int limit = item.cchTextMax - 1;
unsigned i;
unsigned limit = item.cchTextMax - 1;
for (i = 0; i < limit; i++)
{
wchar_t c = temp[i];
wchar_t c = (Byte)temp[i];
if (c == 0)
break;
item.pszText[i] = c;
text[i] = c;
}
item.pszText[i] = 0;
text[i] = 0;
}
return 0;
}
@@ -606,7 +676,7 @@ void CPanel::Refresh_StatusBar()
if (indices.Size() > 0)
{
// for (int ttt = 0; ttt < 1000; ttt++) {
// for (unsigned ttt = 0; ttt < 1000; ttt++) {
UInt64 totalSize = 0;
FOR_VECTOR (i, indices)
totalSize += GetItemSize(indices[i]);
@@ -632,10 +702,10 @@ void CPanel::Refresh_StatusBar()
char dateString2[32];
dateString2[0] = 0;
ConvertPropertyToShortString(dateString2, prop, kpidMTime, false);
for (int i = 0;; i++)
for (unsigned i = 0;; i++)
{
char c = dateString2[i];
dateString[i] = c;
dateString[i] = (Byte)c;
if (c == 0)
break;
}

View File

@@ -49,11 +49,12 @@ void CPanel::InvokeSystemCommand(const char *command)
contextMenu->InvokeCommand(&ci);
}
static const wchar_t *kSeparator = L"----------------------------\n";
static const wchar_t *kSeparatorSmall = L"----\n";
static const wchar_t *kPropValueSeparator = L": ";
static const char *kSeparator = "----------------------------\n";
static const char *kSeparatorSmall = "----\n";
static const char *kPropValueSeparator = ": ";
extern UString ConvertSizeToString(UInt64 value);
extern UString ConvertSizeToString(UInt64 value) throw();
bool IsSizeProp(UINT propID) throw();
UString GetOpenArcErrorMessage(UInt32 errorFlags);
@@ -74,20 +75,7 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR,
val = GetOpenArcErrorMessage(flags);
}
if (val.IsEmpty())
if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && (
propID == kpidSize ||
propID == kpidPackSize ||
propID == kpidNumSubDirs ||
propID == kpidNumSubFiles ||
propID == kpidNumBlocks ||
propID == kpidClusterSize ||
propID == kpidTotalSize ||
propID == kpidFreeSpace ||
propID == kpidPhySize ||
propID == kpidHeadersSize ||
propID == kpidFreeSpace ||
propID == kpidUnpackSize
))
if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID))
{
UInt64 v = 0;
ConvertPropVariantToUInt64(prop, v);
@@ -99,13 +87,13 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR,
if (!val.IsEmpty())
{
s += GetNameOfProperty(propID, nameBSTR);
s += kPropValueSeparator;
s.AddAscii(kPropValueSeparator);
/*
if (propID == kpidComment)
s += L'\n';
s.Add_LF();
*/
s += val;
s += L'\n';
s.Add_LF();
}
}
}
@@ -210,21 +198,21 @@ void CPanel::Properties()
}
}
message += GetNameOfProperty(propID, name);
message += kPropValueSeparator;
message += GetUnicodeString(s);
message += L'\n';
message.AddAscii(kPropValueSeparator);
message.AddAscii(s);
message.Add_LF();
}
}
}
message += kSeparator;
message.AddAscii(kSeparator);
}
/*
message += LangString(IDS_PROP_FILE_TYPE, 0x02000214);
AddLangString(message, IDS_PROP_FILE_TYPE);
message += kPropValueSeparator;
message += GetFolderTypeID();
message += L"\n";
message.Add_LF();
*/
{
@@ -277,7 +265,7 @@ void CPanel::Properties()
{
const int kNumSpecProps = ARRAY_SIZE(kSpecProps);
message += kSeparator;
message.AddAscii(kSeparator);
for (Int32 i = -(int)kNumSpecProps; i < (Int32)numProps; i++)
{
@@ -302,7 +290,7 @@ void CPanel::Properties()
UInt32 numProps;
if (getProps->GetArcNumProps2(level, &numProps) == S_OK)
{
message += kSeparatorSmall;
message.AddAscii(kSeparatorSmall);
for (Int32 i = 0; i < (Int32)numProps; i++)
{
CMyComBSTR name;
@@ -414,9 +402,7 @@ HRESULT CPanel::CreateShellContextMenu(
FOR_VECTOR (i, operatedIndices)
{
LPITEMIDLIST pidl;
UString fileName = GetItemRelPath(operatedIndices[i]);
if (IsFSDrivesFolder())
fileName += WCHAR_PATH_SEPARATOR;
UString fileName = GetItemRelPath2(operatedIndices[i]);
RINOK(parentFolder->ParseDisplayName(GetParent(), 0,
(wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0));
pidls.AddInReserved(pidl);
@@ -574,11 +560,11 @@ void CPanel::CreateSevenZipMenu(HMENU menuSpec,
if (contextMenu.QueryInterface(IID_IInitContextMenu, &initContextMenu) != S_OK)
return;
*/
UString currentFolderUnicode = _currentFolderPrefix;
UString currentFolderUnicode = GetFsPath();
UStringVector names;
unsigned i;
for (i = 0; i < operatedIndices.Size(); i++)
names.Add(currentFolderUnicode + GetItemRelPath(operatedIndices[i]));
names.Add(currentFolderUnicode + GetItemRelPath2(operatedIndices[i]));
CRecordVector<const wchar_t *> namePointers;
for (i = 0; i < operatedIndices.Size(); i++)
namePointers.Add(names[i]);
@@ -598,6 +584,74 @@ void CPanel::CreateSevenZipMenu(HMENU menuSpec,
}
}
static bool IsReadOnlyFolder(IFolderFolder *folder)
{
if (!folder)
return false;
bool res = false;
{
NCOM::CPropVariant prop;
if (folder->GetFolderProperty(kpidReadOnly, &prop) == S_OK)
if (prop.vt == VT_BOOL)
res = VARIANT_BOOLToBool(prop.boolVal);
}
return res;
}
bool CPanel::IsThereReadOnlyFolder() const
{
if (!_folderOperations)
return true;
if (IsReadOnlyFolder(_folder))
return true;
FOR_VECTOR (i, _parentFolders)
{
if (IsReadOnlyFolder(_parentFolders[i].ParentFolder))
return true;
}
return false;
}
bool CPanel::CheckBeforeUpdate(UINT resourceID)
{
if (!_folderOperations)
{
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
// resourceID = resourceID;
// MessageBoxErrorForUpdate(E_NOINTERFACE, resourceID);
return false;
}
for (int i = (int)_parentFolders.Size(); i >= 0; i--)
{
IFolderFolder *folder;
if (i == (int)_parentFolders.Size())
folder = _folder;
else
folder = _parentFolders[i].ParentFolder;
if (!IsReadOnlyFolder(folder))
continue;
UString s;
AddLangString(s, resourceID);
s.Add_LF();
AddLangString(s, IDS_OPERATION_IS_NOT_SUPPORTED);
s.Add_LF();
if (i == 0)
s += GetFolderPath(folder);
else
s += _parentFolders[i - 1].VirtualPath;
s.Add_LF();
AddLangString(s, IDS_PROP_READ_ONLY);
MessageBoxMyError(s);
return false;
}
return true;
}
void CPanel::CreateFileMenu(HMENU menuSpec,
CMyComPtr<IContextMenu> &sevenZipContextMenu,
CMyComPtr<IContextMenu> &systemContextMenu,
@@ -631,8 +685,38 @@ void CPanel::CreateFileMenu(HMENU menuSpec,
if (IsItem_Folder(operatedIndices[i]))
break;
bool allAreFiles = (i == operatedIndices.Size());
LoadFileMenu(menu, menu.GetItemCount(), programMenu,
IsFSFolder(), operatedIndices.Size(), allAreFiles);
CFileMenu fm;
fm.readOnly = IsThereReadOnlyFolder();
fm.isFsFolder = Is_IO_FS_Folder();
fm.programMenu = programMenu;
fm.allAreFiles = allAreFiles;
fm.numItems = operatedIndices.Size();
fm.isAltStreamsSupported = false;
if (_folderAltStreams)
{
if (operatedIndices.Size() <= 1)
{
Int32 realIndex = -1;
if (operatedIndices.Size() == 1)
realIndex = operatedIndices[0];
Int32 val = 0;
if (_folderAltStreams->AreAltStreamsSupported(realIndex, &val) == S_OK)
fm.isAltStreamsSupported = IntToBool(val);
}
}
else
{
if (fm.numItems == 0)
fm.isAltStreamsSupported = IsFSFolder();
else
fm.isAltStreamsSupported = IsFolder_with_FsItems();
}
fm.Load(menu, menu.GetItemCount());
}
bool CPanel::InvokePluginCommand(int id)
@@ -654,26 +738,31 @@ bool CPanel::InvokePluginCommand(int id,
else
offset = id - kSevenZipStartMenuID;
#ifndef use_CMINVOKECOMMANDINFOEXR
CMINVOKECOMMANDINFO
#ifdef use_CMINVOKECOMMANDINFOEX
CMINVOKECOMMANDINFOEX
#else
CMINVOKECOMMANDINFOEX
CMINVOKECOMMANDINFO
#endif
commandInfo;
commandInfo;
memset(&commandInfo, 0, sizeof(commandInfo));
commandInfo.cbSize = sizeof(commandInfo);
commandInfo.fMask = 0
#ifdef use_CMINVOKECOMMANDINFOEXR
| CMIC_MASK_UNICODE
#ifdef use_CMINVOKECOMMANDINFOEX
| CMIC_MASK_UNICODE
#endif
;
;
commandInfo.hwnd = GetParent();
commandInfo.lpVerb = (LPCSTR)(MAKEINTRESOURCE(offset));
commandInfo.lpParameters = NULL;
CSysString currentFolderSys = GetSystemString(_currentFolderPrefix);
commandInfo.lpDirectory = (LPCSTR)(LPCTSTR)(currentFolderSys);
commandInfo.nShow = SW_SHOW;
#ifdef use_CMINVOKECOMMANDINFOEXR
#ifdef use_CMINVOKECOMMANDINFOEX
commandInfo.lpParametersW = NULL;
commandInfo.lpTitle = "";
commandInfo.lpVerbW = (LPCWSTR)(MAKEINTRESOURCEW(offset));
@@ -684,7 +773,9 @@ bool CPanel::InvokePluginCommand(int id,
// commandInfo.ptInvoke.y = yPos;
commandInfo.ptInvoke.x = 0;
commandInfo.ptInvoke.y = 0;
#endif
HRESULT result;
if (isSystemMenu)
result = systemContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo));

View File

@@ -85,16 +85,15 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr
ProgressDialog.Sync.FinalMessage.ErrorMessage.Title = titleError;
Result = S_OK;
bool usePassword = false;
UString password;
UpdateCallbackSpec->Init();
if (panel._parentFolders.Size() > 0)
{
const CFolderLink &fl = panel._parentFolders.Back();
usePassword = fl.UsePassword;
password = fl.Password;
UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword;
UpdateCallbackSpec->Password = fl.Password;
}
UpdateCallbackSpec->Init(usePassword, password);
ProgressDialog.MainWindow = panel._mainWindow; // panel.GetParent()
ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE);
@@ -108,6 +107,7 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr
typedef int (WINAPI * SHFileOperationWP)(LPSHFILEOPSTRUCTW lpFileOp);
#endif
/*
void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID)
{
if (errorCode == E_NOINTERFACE)
@@ -115,6 +115,7 @@ void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID)
else
MessageBoxError(errorCode, LangString(resourceID));
}
*/
void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
{
@@ -137,8 +138,8 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
CDynamicBuffer<CHAR> buffer;
FOR_VECTOR (i, indices)
{
const AString path = GetSystemString(GetFsPath() + GetItemRelPath(indices[i]));
memcpy(buffer.GetCurPtrAndGrow(path.Len() + 1), (const CHAR *)path, (path.Len() + 1) * sizeof(CHAR));
const AString path = GetSystemString(GetItemFullPath(indices[i]));
buffer.AddData(path, path.Len() + 1);
}
*buffer.GetCurPtrAndGrow(1) = 0;
SHFILEOPSTRUCTA fo;
@@ -163,13 +164,14 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
{
CDynamicBuffer<WCHAR> buffer;
unsigned maxLen = 0;
const UString prefix = GetFsPath();
FOR_VECTOR (i, indices)
{
// L"\\\\?\\") doesn't work here.
const UString path = GetFsPath() + GetItemRelPath(indices[i]);
const UString path = prefix + GetItemRelPath2(indices[i]);
if (path.Len() > maxLen)
maxLen = path.Len();
memcpy(buffer.GetCurPtrAndGrow(path.Len() + 1), (const WCHAR *)path, (path.Len() + 1) * sizeof(WCHAR));
buffer.AddData(path, path.Len() + 1);
}
*buffer.GetCurPtrAndGrow(1) = 0;
if (maxLen >= MAX_PATH)
@@ -220,19 +222,15 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
// DeleteItemsInternal
CMyComPtr<IFolderOperations> folderOperations;
if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
{
MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_DELETING);
if (!CheckBeforeUpdate(IDS_ERROR_DELETING))
return;
}
UInt32 titleID, messageID;
UString messageParam;
if (indices.Size() == 1)
{
int index = indices[0];
messageParam = GetItemRelPath(index);
messageParam = GetItemRelPath2(index);
if (IsItem_Folder(index))
{
titleID = IDS_CONFIRM_FOLDER_DELETE;
@@ -256,7 +254,7 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
CDisableNotify disableNotify(*this);
{
CThreadFolderOperations op(FOLDER_TYPE_DELETE);
op.FolderOperations = folderOperations;
op.FolderOperations = _folderOperations;
op.Indices = indices;
op.DoOperation(*this,
LangString(IDS_DELETING),
@@ -271,25 +269,14 @@ BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh)
int realIndex = GetRealIndex(lpnmh->item);
if (realIndex == kParentIndex)
return TRUE;
CMyComPtr<IFolderOperations> folderOperations;
if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
if (IsThereReadOnlyFolder())
return TRUE;
return FALSE;
}
static UString GetLastPart(const UString name)
{
int slashPos = name.ReverseFind(L'/');
#ifdef _WIN32
int slash1Pos = name.ReverseFind(L'\\');
slashPos = MyMax(slashPos, slash1Pos);
#endif
return name.Ptr(slashPos + 1);
}
bool IsCorrectFsName(const UString &name)
{
const UString lastPart = GetLastPart(name);
const UString lastPart = name.Ptr(name.ReverseFind_PathSepar() + 1);
return
lastPart != L"." &&
lastPart != L"..";
@@ -299,7 +286,7 @@ bool CorrectFsPath(const UString &relBase, const UString &path, UString &result)
bool CPanel::CorrectFsPath(const UString &path2, UString &result)
{
return ::CorrectFsPath(_currentFolderPrefix, path2, result);
return ::CorrectFsPath(GetFsPath(), path2, result);
}
BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
@@ -307,12 +294,10 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
if (lpnmh->item.pszText == NULL)
return FALSE;
CDisableTimerProcessing disableTimerProcessing2(*this);
CMyComPtr<IFolderOperations> folderOperations;
if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
{
MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_RENAMING);
if (!CheckBeforeUpdate(IDS_ERROR_RENAMING))
return FALSE;
}
UString newName = lpnmh->item.pszText;
if (!IsCorrectFsName(newName))
{
@@ -342,7 +327,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
CDisableNotify disableNotify(*this);
{
CThreadFolderOperations op(FOLDER_TYPE_RENAME);
op.FolderOperations = folderOperations;
op.FolderOperations = _folderOperations;
op.Index = realIndex;
op.Name = newName;
/* HRESULTres = */ op.DoOperation(*this,
@@ -377,12 +362,9 @@ bool Dlg_CreateFolder(HWND wnd, UString &destName);
void CPanel::CreateFolder()
{
CMyComPtr<IFolderOperations> folderOperations;
if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
{
MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FOLDER_ERROR);
if (!CheckBeforeUpdate(IDS_CREATE_FOLDER_ERROR))
return;
}
CDisableTimerProcessing disableTimerProcessing2(*this);
CSelectedState state;
SaveSelectedState(state);
@@ -412,7 +394,7 @@ void CPanel::CreateFolder()
CDisableNotify disableNotify(*this);
{
CThreadFolderOperations op(FOLDER_TYPE_CREATE_FOLDER);
op.FolderOperations = folderOperations;
op.FolderOperations = _folderOperations;
op.Name = newName;
res = op.DoOperation(*this,
LangString(IDS_CREATE_FOLDER),
@@ -439,12 +421,9 @@ void CPanel::CreateFolder()
void CPanel::CreateFile()
{
CMyComPtr<IFolderOperations> folderOperations;
if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
{
MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FILE_ERROR);
if (!CheckBeforeUpdate(IDS_CREATE_FILE_ERROR))
return;
}
CDisableTimerProcessing disableTimerProcessing2(*this);
CSelectedState state;
SaveSelectedState(state);
@@ -471,10 +450,11 @@ void CPanel::CreateFile()
newName = correctName;
}
HRESULT result = folderOperations->CreateFile(newName, 0);
HRESULT result = _folderOperations->CreateFile(newName, 0);
if (result != S_OK)
{
MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR);
MessageBoxError(result, LangString(IDS_CREATE_FILE_ERROR));
// MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR);
return;
}
int pos = newName.Find(WCHAR_PATH_SEPARATOR);
@@ -489,6 +469,8 @@ void CPanel::CreateFile()
void CPanel::RenameFile()
{
if (!CheckBeforeUpdate(IDS_ERROR_RENAMING))
return;
int index = _listView.GetFocusedItem();
if (index >= 0)
_listView.EditLabel(index);
@@ -496,6 +478,8 @@ void CPanel::RenameFile()
void CPanel::ChangeComment()
{
if (!CheckBeforeUpdate(IDS_COMMENT))
return;
CDisableTimerProcessing disableTimerProcessing2(*this);
int index = _listView.GetFocusedItem();
if (index < 0)
@@ -505,13 +489,6 @@ void CPanel::ChangeComment()
return;
CSelectedState state;
SaveSelectedState(state);
CMyComPtr<IFolderOperations> folderOperations;
if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
{
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
}
UString comment;
{
NCOM::CPropVariant propVariant;
@@ -522,17 +499,19 @@ void CPanel::ChangeComment()
else if (propVariant.vt != VT_EMPTY)
return;
}
UString name = GetItemRelPath(realIndex);
UString name = GetItemRelPath2(realIndex);
CComboDialog dlg;
dlg.Title = name + L' ' + LangString(IDS_COMMENT);
dlg.Title = name;
dlg.Title += L" : ";
AddLangString(dlg.Title, IDS_COMMENT);
dlg.Value = comment;
LangString(IDS_COMMENT2, dlg.Static);
if (dlg.Create(GetParent()) != IDOK)
return;
NCOM::CPropVariant propVariant = (const wchar_t *)dlg.Value;
NCOM::CPropVariant propVariant = dlg.Value.Ptr();
CDisableNotify disableNotify(*this);
HRESULT result = folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL);
HRESULT result = _folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL);
if (result != S_OK)
{
if (result == E_NOINTERFACE)

View File

@@ -22,7 +22,9 @@ void CPanel::OnShiftSelectMessage()
return;
int startItem = MyMin(focusedItem, _prevFocusedItem);
int finishItem = MyMax(focusedItem, _prevFocusedItem);
for (int i = 0; i < _listView.GetItemCount(); i++)
int numItems = _listView.GetItemCount();
for (int i = 0; i < numItems; i++)
{
int realIndex = GetRealItemIndex(i);
if (realIndex == kParentIndex)
@@ -34,6 +36,7 @@ void CPanel::OnShiftSelectMessage()
_listView.RedrawItem(i);
}
}
_prevFocusedItem = focusedItem;
}
@@ -45,6 +48,7 @@ void CPanel::OnArrowWithShift()
if (focusedItem < 0)
return;
int realIndex = GetRealItemIndex(focusedItem);
if (_selectionIsDefined)
{
if (realIndex != kParentIndex)
@@ -64,6 +68,7 @@ void CPanel::OnArrowWithShift()
_selectedStatusVector[realIndex] = _selectMark;
}
}
_prevFocusedItem = focusedItem;
PostMessage(kShiftSelectMessage);
_listView.RedrawItem(focusedItem);
@@ -165,13 +170,6 @@ void CPanel::SelectByType(bool selectMode)
UString name = GetItemName(realIndex);
bool isItemFolder = IsItem_Folder(realIndex);
/*
UInt32 numItems;
_folder->GetNumberOfItems(&numItems);
if ((UInt32)_selectedStatusVector.Size() != numItems)
throw 11111;
*/
if (isItemFolder)
{
FOR_VECTOR (i, _selectedStatusVector)
@@ -180,11 +178,11 @@ void CPanel::SelectByType(bool selectMode)
}
else
{
int pos = name.ReverseFind(L'.');
int pos = name.ReverseFind_Dot();
if (pos < 0)
{
FOR_VECTOR (i, _selectedStatusVector)
if (IsItem_Folder(i) == isItemFolder && GetItemName(i).ReverseFind(L'.') < 0)
if (IsItem_Folder(i) == isItemFolder && GetItemName(i).ReverseFind_Dot() < 0)
_selectedStatusVector[i] = selectMode;
}
else
@@ -196,6 +194,7 @@ void CPanel::SelectByType(bool selectMode)
_selectedStatusVector[i] = selectMode;
}
}
UpdateSelection();
}
@@ -253,10 +252,11 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)
{
if (itemActivate->hdr.hwndFrom != HWND(_listView))
return;
// It will be work only for Version 4.71 (IE 4);
// It will work only for Version 4.71 (IE 4);
int indexInList = itemActivate->iItem;
if (indexInList < 0)
return;
#ifndef UNDER_CE
if ((itemActivate->uKeyFlags & LVKF_SHIFT) != 0)
{
@@ -264,9 +264,11 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)
int focusedIndex = _startGroupSelect;
if (focusedIndex < 0)
return;
unsigned startItem = MyMin((unsigned)focusedIndex, (unsigned)indexInList);
unsigned finishItem = MyMax((unsigned)focusedIndex, (unsigned)indexInList);
FOR_VECTOR (i, _selectedStatusVector)
int startItem = MyMin(focusedIndex, indexInList);
int finishItem = MyMax(focusedIndex, indexInList);
int numItems = _listView.GetItemCount();
for (int i = 0; i < numItems; i++)
{
int realIndex = GetRealItemIndex(i);
if (realIndex == kParentIndex)
@@ -283,6 +285,7 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)
#endif
{
_startGroupSelect = indexInList;
#ifndef UNDER_CE
if ((itemActivate->uKeyFlags & LVKF_CONTROL) != 0)
{
@@ -295,5 +298,6 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)
}
#endif
}
return;
}

View File

@@ -76,7 +76,7 @@ static int CompareFileNames_Le16(const Byte *s1, unsigned size1, const Byte *s2,
static inline const wchar_t *GetExtensionPtr(const UString &name)
{
int dotPos = name.ReverseFind(L'.');
int dotPos = name.ReverseFind_Dot();
return name.Ptr((dotPos < 0) ? name.Len() : dotPos);
}

View File

@@ -138,7 +138,7 @@ HRESULT CThreadSplit::ProcessVirt()
if (!outFile.Create(name, false))
{
HRESULT res = GetLastError();
SetErrorPath1(name);
AddErrorPath(name);
return res;
}
}
@@ -165,7 +165,7 @@ void CApp::Split()
{
int srcPanelIndex = GetFocusedPanelIndex();
CPanel &srcPanel = Panels[srcPanelIndex];
if (!srcPanel.IsFSFolder())
if (!srcPanel.Is_IO_FS_Folder())
{
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
@@ -187,13 +187,13 @@ void CApp::Split()
}
const UString itemName = srcPanel.GetItemName(index);
UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
UString path = srcPath;
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &destPanel = Panels[destPanelIndex];
if (NumPanels > 1)
if (destPanel.IsFSFolder())
path = destPanel._currentFolderPrefix;
path = destPanel.GetFsPath();
CSplitDialog splitDialog;
splitDialog.FilePath = srcPanel.GetItemRelPath(index);
splitDialog.Path = path;
@@ -243,12 +243,13 @@ void CApp::Split()
progressDialog.MainWindow = _window;
progressDialog.MainTitle = progressWindowTitle;
progressDialog.MainAddTitle = title + L' ';
progressDialog.MainAddTitle = title;
progressDialog.MainAddTitle.Add_Space();
progressDialog.Sync.Set_TitleFileName(itemName);
spliter.FilePath = us2fs(srcPath + itemName);
spliter.VolBasePath = us2fs(path + itemName);
spliter.VolBasePath = us2fs(path + srcPanel.GetItemName_for_Copy(index));
spliter.VolumeSizes = splitDialog.VolumeSizes;
// if (splitDialog.VolumeSizes.Size() == 0) return;
@@ -285,7 +286,7 @@ HRESULT CThreadCombine::ProcessVirt()
if (!outFile.Create(OutputPath, false))
{
HRESULT res = GetLastError();
SetErrorPath1(OutputPath);
AddErrorPath(OutputPath);
return res;
}
@@ -304,7 +305,7 @@ HRESULT CThreadCombine::ProcessVirt()
if (!inFile.Open(nextName))
{
HRESULT res = GetLastError();
SetErrorPath1(nextName);
AddErrorPath(nextName);
return res;
}
sync.Set_FilePath(fs2us(nextName));
@@ -314,7 +315,7 @@ HRESULT CThreadCombine::ProcessVirt()
if (!inFile.Read(buffer, kBufSize, processedSize))
{
HRESULT res = GetLastError();
SetErrorPath1(nextName);
AddErrorPath(nextName);
return res;
}
if (processedSize == 0)
@@ -323,7 +324,7 @@ HRESULT CThreadCombine::ProcessVirt()
if (!outFile.Write(buffer, needSize, processedSize))
{
HRESULT res = GetLastError();
SetErrorPath1(OutputPath);
AddErrorPath(OutputPath);
return res;
}
if (needSize != processedSize)
@@ -364,13 +365,13 @@ void CApp::Combine()
}
const UString itemName = srcPanel.GetItemName(index);
UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
UString path = srcPath;
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &destPanel = Panels[destPanelIndex];
if (NumPanels > 1)
if (destPanel.IsFSFolder())
path = destPanel._currentFolderPrefix;
path = destPanel.GetFsPath();
CVolSeqName volSeqName;
if (!volSeqName.ParseName(itemName))
@@ -408,7 +409,7 @@ void CApp::Combine()
UString info;
AddValuePair2(info, IDS_PROP_FILES, combiner.Names.Size(), combiner.TotalSize);
info += L"\n";
info.Add_LF();
info += srcPath;
unsigned i;
@@ -425,7 +426,7 @@ void CApp::Combine()
CCopyDialog copyDialog;
copyDialog.Value = path;
LangString(IDS_COMBINE, copyDialog.Title);
copyDialog.Title += ' ';
copyDialog.Title.Add_Space();
copyDialog.Title += srcPanel.GetItemRelPath(index);
LangString(IDS_COMBINE_TO, copyDialog.Static);
copyDialog.Info = info;
@@ -468,7 +469,8 @@ void CApp::Combine()
progressDialog.MainWindow = _window;
progressDialog.MainTitle = progressWindowTitle;
progressDialog.MainAddTitle = title + L' ';
progressDialog.MainAddTitle = title;
progressDialog.MainAddTitle.Add_Space();
combiner.InputDirPrefix = us2fs(srcPath);

View File

@@ -11,7 +11,7 @@
PLUGIN_INTERFACE(IInitContextMenu, 0x00)
{
STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UInt32 numFiles) PURE;
STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t * const *names, UInt32 numFiles) PURE;
};
PLUGIN_INTERFACE(IPluginOptionsCallback, 0x01)

View File

@@ -28,7 +28,7 @@ static const UINT kTimerElapse =
#ifdef UNDER_CE
500
#else
100
200
#endif
;
@@ -104,13 +104,13 @@ HRESULT CProgressSync::CheckStop()
}
}
HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir)
HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir)
{
{
CRITICAL_LOCK
_totalFiles = numFiles;
_totalBytes = totalSize;
_filePath = fileName;
_filePath = fs2us(fileName);
_isDir = isDir;
// _completedBytes = 0;
CHECK_STOP
@@ -118,10 +118,14 @@ HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const USt
return CheckStop();
}
void CProgressSync::Set_NumFilesTotal(UInt64 val)
HRESULT CProgressSync::Set_NumFilesTotal(UInt64 val)
{
CRITICAL_LOCK
_totalFiles = val;
{
CRITICAL_LOCK
_totalFiles = val;
CHECK_STOP
}
return CheckStop();
}
void CProgressSync::Set_NumBytesTotal(UInt64 val)
@@ -171,16 +175,34 @@ void CProgressSync::Set_TitleFileName(const UString &fileName)
CRITICAL_LOCK
_titleFileName = fileName;
}
void CProgressSync::Set_Status(const UString &s)
{
CRITICAL_LOCK
_status = s;
}
void CProgressSync::Set_FilePath(const UString &path, bool isDir)
HRESULT CProgressSync::Set_Status2(const UString &s, const wchar_t *path, bool isDir)
{
{
CRITICAL_LOCK
_status = s;
if (path)
_filePath = path;
else
_filePath.Empty();
_isDir = isDir;
}
return CheckStop();
}
void CProgressSync::Set_FilePath(const wchar_t *path, bool isDir)
{
CRITICAL_LOCK
_filePath = path;
if (path)
_filePath = path;
else
_filePath.Empty();
_isDir = isDir;
}
@@ -199,7 +221,7 @@ void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t
if (message && *message != 0 )
{
if (!s.IsEmpty())
s += L'\n';
s.Add_LF();
s += message;
if (!s.IsEmpty() && s.Back() == L'\n')
s.DeleteBack();
@@ -633,7 +655,6 @@ static unsigned GetPower64(UInt64 val)
if (high == 0)
return GetPower32((UInt32)val);
return GetPower32(high) + 32;
}
static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider)
@@ -867,7 +888,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
s1 = _filePath;
else
{
int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);
int slashPos = _filePath.ReverseFind_PathSepar();
if (slashPos >= 0)
{
s1.SetFrom(_filePath, slashPos + 1);
@@ -878,7 +899,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
}
ReduceString(s1, _numReduceSymbols);
ReduceString(s2, _numReduceSymbols);
s1 += L'\n';
s1.Add_LF();
s1 += s2;
SetItemText(IDT_PROGRESS_FILE_NAME, s1);
}
@@ -1025,22 +1046,22 @@ void CProgressDialog::SetTitleText()
if (Sync.Get_Paused())
{
s += _paused_String;
s += L' ';
s.Add_Space();
}
if (IS_DEFINED_VAL(_prevPercentValue))
{
wchar_t temp[32];
char temp[32];
ConvertUInt64ToString(_prevPercentValue, temp);
s += temp;
s.AddAscii(temp);
s += L'%';
}
if (!_foreground)
{
s += L' ';
s.Add_Space();
s += _backgrounded_String;
}
s += L' ';
s.Add_Space();
#ifndef _SFX
{
unsigned len = s.Len();
@@ -1055,7 +1076,7 @@ void CProgressDialog::SetTitleText()
{
UString fileName = _titleFileName;
ReduceString(fileName, kTitleFileNameSizeLimit);
s += L' ';
s.Add_Space();
s += fileName;
}
SetText(s);
@@ -1239,7 +1260,7 @@ static void AddMessageToString(UString &dest, const UString &src)
if (!src.IsEmpty())
{
if (!dest.IsEmpty())
dest += L'\n';
dest.Add_LF();
dest += src;
}
}
@@ -1266,8 +1287,15 @@ void CProgressThreadVirt::Process()
m = HResultToMessage(Result);
}
AddMessageToString(m, FinalMessage.ErrorMessage.Message);
AddMessageToString(m, fs2us(ErrorPath1));
AddMessageToString(m, fs2us(ErrorPath2));
{
FOR_VECTOR(i, ErrorPaths)
{
if (i >= 32)
break;
AddMessageToString(m, fs2us(ErrorPaths[i]));
}
}
CProgressSync &sync = ProgressDialog.Sync;
NSynchronization::CCriticalSectionLock lock(sync._cs);

View File

@@ -80,9 +80,9 @@ public:
}
HRESULT CheckStop();
HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir = false);
HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false);
void Set_NumFilesTotal(UInt64 val);
HRESULT Set_NumFilesTotal(UInt64 val);
void Set_NumBytesTotal(UInt64 val);
void Set_NumFilesCur(UInt64 val);
HRESULT Set_NumBytesCur(const UInt64 *val);
@@ -91,7 +91,8 @@ public:
void Set_TitleFileName(const UString &fileName);
void Set_Status(const UString &s);
void Set_FilePath(const UString &path, bool isDir = false);
HRESULT Set_Status2(const UString &s, const wchar_t *path, bool isDir = false);
void Set_FilePath(const wchar_t *path, bool isDir = false);
void AddError_Message(const wchar_t *message);
void AddError_Message_Name(const wchar_t *message, const wchar_t *name);
@@ -274,9 +275,8 @@ public:
class CProgressThreadVirt
{
FString ErrorPath1;
FString ErrorPath2;
protected:
FStringVector ErrorPaths;
CProgressFinalMessage FinalMessage;
// error if any of HRESULT, ErrorMessage, ErrorPath
@@ -299,8 +299,7 @@ public:
return 0;
}
void SetErrorPath1(const FString &path) { ErrorPath1 = path; }
void SetErrorPath2(const FString &path) { ErrorPath2 = path; }
void AddErrorPath(const FString &path) { ErrorPaths.Add(path); }
HRESULT Create(const UString &title, HWND parentWindow = 0);
CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {}

View File

@@ -94,4 +94,6 @@ BEGIN
IDS_PROP_HARD_LINK "Hard Link"
IDS_PROP_INODE "iNode"
IDS_PROP_STREAM_ID "Stream ID"
IDS_PROP_READ_ONLY "Read-only"
IDS_PROP_OUT_NAME "Out Name"
END

View File

@@ -90,3 +90,5 @@
#define IDS_PROP_HARD_LINK 1090
#define IDS_PROP_INODE 1091
#define IDS_PROP_STREAM_ID 1092
#define IDS_PROP_READ_ONLY 1093
#define IDS_PROP_OUT_NAME 1094

View File

@@ -86,8 +86,7 @@ bool CShellExtInfo::ReadFromRegistry(HKEY hkey, const CSysString &ext)
bool CShellExtInfo::IsIt7Zip() const
{
UString s = GetUnicodeString(k7zipPrefix);
return MyStringCompareNoCase_N(GetUnicodeString(ProgramKey), s, s.Len()) == 0;
return IsString1PrefixedByString2_NoCase(GetUnicodeString(ProgramKey), GetUnicodeString(k7zipPrefix));
}
LONG DeleteShellExtensionInfo(HKEY hkey, const CSysString &ext)

View File

@@ -10,11 +10,25 @@
#include "../../PropID.h"
#if defined(_WIN32) && !defined(UNDER_CE)
#define USE_WIN_PATHS
#endif
static const unsigned kNumRootFolderItems =
#ifdef USE_WIN_PATHS
4
#else
1
#endif
;
#include "FSFolder.h"
#include "LangUtils.h"
#ifndef UNDER_CE
#ifdef USE_WIN_PATHS
#include "NetFolder.h"
#include "FSDrives.h"
#include "AltStreamsFolder.h"
#endif
#include "RootFolder.h"
#include "SysIconUtils.h"
@@ -30,10 +44,10 @@ static const PROPID kProps[] =
UString RootFolder_GetName_Computer(int &iconIndex)
{
#ifdef UNDER_CE
GetRealIconIndex(FTEXT("\\"), FILE_ATTRIBUTE_DIRECTORY, iconIndex);
#else
#ifdef USE_WIN_PATHS
iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES);
#else
GetRealIconIndex(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, iconIndex);
#endif
return LangString(IDS_COMPUTER);
}
@@ -53,21 +67,21 @@ UString RootFolder_GetName_Documents(int &iconIndex)
enum
{
ROOT_INDEX_COMPUTER = 0
#ifndef UNDER_CE
#ifdef USE_WIN_PATHS
, ROOT_INDEX_DOCUMENTS
, ROOT_INDEX_NETWORK
, ROOT_INDEX_VOLUMES
#endif
};
#ifndef UNDER_CE
#ifdef USE_WIN_PATHS
static const wchar_t *kVolPrefix = L"\\\\.";
#endif
void CRootFolder::Init()
{
_names[ROOT_INDEX_COMPUTER] = RootFolder_GetName_Computer(_iconIndices[ROOT_INDEX_COMPUTER]);
#ifndef UNDER_CE
#ifdef USE_WIN_PATHS
_names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]);
_names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]);
_names[ROOT_INDEX_VOLUMES] = kVolPrefix;
@@ -124,8 +138,7 @@ UString GetMyDocsPath()
us = GetUnicodeString(s2);
}
#endif
if (us.Len() > 0 && us.Back() != WCHAR_PATH_SEPARATOR)
us += WCHAR_PATH_SEPARATOR;
NFile::NName::NormalizeDirPathPrefix(us);
return us;
}
@@ -133,14 +146,8 @@ STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolde
{
*resultFolder = NULL;
CMyComPtr<IFolderFolder> subFolder;
#ifdef UNDER_CE
if (index == ROOT_INDEX_COMPUTER)
{
NFsFolder::CFSFolder *fsFolder = new NFsFolder::CFSFolder;
subFolder = fsFolder;
fsFolder->InitToRoot();
}
#else
#ifdef USE_WIN_PATHS
if (index == ROOT_INDEX_COMPUTER || index == ROOT_INDEX_VOLUMES)
{
CFSDrives *fsDrivesSpec = new CFSDrives;
@@ -160,12 +167,20 @@ STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolde
{
NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
subFolder = fsFolderSpec;
RINOK(fsFolderSpec->Init(us2fs(s), NULL));
RINOK(fsFolderSpec->Init(us2fs(s)));
}
}
#else
if (index == ROOT_INDEX_COMPUTER)
{
NFsFolder::CFSFolder *fsFolder = new NFsFolder::CFSFolder;
subFolder = fsFolder;
fsFolder->InitToRoot();
}
#endif
else
return E_INVALIDARG;
*resultFolder = subFolder.Detach();
return S_OK;
}
@@ -185,6 +200,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu
*resultFolder = 0;
UString name2 = name;
name2.Trim();
if (name2.IsEmpty())
{
CRootFolder *rootFolderSpec = new CRootFolder;
@@ -193,21 +209,25 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu
*resultFolder = rootFolder.Detach();
return S_OK;
}
for (int i = 0; i < kNumRootFolderItems; i++)
for (unsigned i = 0; i < kNumRootFolderItems; i++)
if (AreEqualNames(name2, _names[i]))
return BindToFolder((UInt32)i, resultFolder);
#ifdef UNDER_CE
if (name2 == L"\\")
return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);
#else
#ifdef USE_WIN_PATHS
if (AreEqualNames(name2, L"My Documents") ||
AreEqualNames(name2, L"Documents"))
return BindToFolder((UInt32)ROOT_INDEX_DOCUMENTS, resultFolder);
#else
if (name2 == WSTRING_PATH_SEPARATOR)
return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);
#endif
if (AreEqualNames(name2, L"My Computer") ||
AreEqualNames(name2, L"Computer"))
return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);
if (name2 == UString(WCHAR_PATH_SEPARATOR))
if (name2 == WSTRING_PATH_SEPARATOR)
{
CMyComPtr<IFolderFolder> subFolder = this;
*resultFolder = subFolder.Detach();
@@ -219,7 +239,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu
CMyComPtr<IFolderFolder> subFolder;
#ifndef UNDER_CE
#ifdef USE_WIN_PATHS
if (name2.IsPrefixedBy(kVolPrefix))
{
CFSDrives *folderSpec = new CFSDrives;
@@ -232,16 +252,22 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu
subFolder = folderSpec;
folderSpec->Init(false, true);
}
else if (name2.Back() == ':')
{
NAltStreamsFolder::CAltStreamsFolder *folderSpec = new NAltStreamsFolder::CAltStreamsFolder;
subFolder = folderSpec;
if (folderSpec->Init(us2fs(name2)) != S_OK)
return E_INVALIDARG;
}
else
#endif
{
if (name2[name2.Len() - 1] != WCHAR_PATH_SEPARATOR)
name2 += WCHAR_PATH_SEPARATOR;
NFile::NName::NormalizeDirPathPrefix(name2);
NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
subFolder = fsFolderSpec;
if (fsFolderSpec->Init(us2fs(name2), 0) != S_OK)
if (fsFolderSpec->Init(us2fs(name2)) != S_OK)
{
#ifndef UNDER_CE
#ifdef USE_WIN_PATHS
if (name2[0] == WCHAR_PATH_SEPARATOR)
{
CNetFolder *netFolderSpec = new CNetFolder;
@@ -253,6 +279,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu
return E_INVALIDARG;
}
}
*resultFolder = subFolder.Detach();
return S_OK;
}
@@ -267,11 +294,11 @@ IMP_IFolderFolder_Props(CRootFolder)
STDMETHODIMP CRootFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
switch(propID)
NCOM::CPropVariant prop;
switch (propID)
{
case kpidType: prop = L"RootFolder"; break;
case kpidPath: prop = L""; break;
case kpidType: prop = "RootFolder"; break;
case kpidPath: prop = ""; break;
}
prop.Detach(value);
return S_OK;

View File

@@ -7,21 +7,15 @@
#include "IFolder.h"
const int kNumRootFolderItems =
#ifdef UNDER_CE
1
#else
4
#endif
;
const unsigned kNumRootFolderItems_Max = 4;
class CRootFolder:
public IFolderFolder,
public IFolderGetSystemIconIndex,
public CMyUnknownImp
{
UString _names[kNumRootFolderItems];
int _iconIndices[kNumRootFolderItems];
UString _names[kNumRootFolderItems_Max];
int _iconIndices[kNumRootFolderItems_Max];
public:
MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex)

View File

@@ -1,7 +1,7 @@
#include "SettingsPageRes.h"
#include "../../GuiCommon.rc"
#define xc 200
#define xc 240
#define yc 120
IDD_SETTINGS MY_PAGE

View File

@@ -38,7 +38,7 @@ bool CSplitDialog::OnInit()
{
UString title;
GetText(title);
title += L' ';
title.Add_Space();
title += FilePath;
SetText(title);
}

View File

@@ -54,14 +54,17 @@ void SplitString(const UString &srcString, UStringVector &destStrings)
destStrings.Add(s);
}
/*
UString JoinStrings(const UStringVector &srcStrings)
{
UString s;
FOR_VECTOR (i, srcStrings)
{
if (i != 0)
s += L' ';
s.Add_Space();
s += srcStrings[i];
}
return s;
}
*/

View File

@@ -3,6 +3,7 @@
#include "StdAfx.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/Defs.h"
#include "../../../Windows/DLL.h"
#include "../../../Windows/ErrorMsg.h"
@@ -16,6 +17,10 @@
using namespace NWindows;
#ifndef _UNICODE
extern bool g_IsNT;
#endif
static const UInt32 kLangIDs[] =
{
IDT_SYSTEM_ASSOCIATE
@@ -48,8 +53,8 @@ int CSystemPage::AddIcon(const UString &iconPath, int iconIndex)
// we expand path from REG_EXPAND_SZ registry item.
UString path;
DWORD size = MAX_PATH + 10;
DWORD needLen = ::ExpandEnvironmentStringsW(iconPath, path.GetBuffer((int)size + 1), size);
path.ReleaseBuffer();
DWORD needLen = ::ExpandEnvironmentStringsW(iconPath, path.GetBuf(size + 2), size);
path.ReleaseBuf_CalcLen(size);
if (needLen == 0 || needLen >= size)
path = iconPath;
int num = ExtractIconExW(path, iconIndex, NULL, &hicon, 1);
@@ -140,32 +145,49 @@ bool CSystemPage::OnInit()
_listView.InsertColumn(0, LangString(IDS_PROP_FILE_TYPE), 72);
CSysString s;
UString s;
#if NUM_EXT_GROUPS == 1
s = TEXT("Program");
s.SetFromAscii("Program");
#else
#ifndef UNDER_CE
DWORD size = 256;
BOOL res = GetUserName(s.GetBuffer(size), &size);
s.ReleaseBuffer();
const unsigned kSize = 256;
BOOL res;
DWORD size = kSize;
#ifndef _UNICODE
if (!g_IsNT)
{
AString s2;
res = GetUserNameA(s2.GetBuf(size), &size);
s2.ReleaseBuf_CalcLen(MyMin((unsigned)size, kSize));
s = GetUnicodeString(s2);
}
else
#endif
{
res = GetUserNameW(s.GetBuf(size), &size);
s.ReleaseBuf_CalcLen(MyMin((unsigned)size, kSize));
}
if (!res)
#endif
s = TEXT("Current User");
s.SetFromAscii("Current User");
#endif
LVCOLUMN ci;
LV_COLUMNW ci;
ci.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
ci.cx = 100;
ci.pszText = (TCHAR *)(const TCHAR *)s;
ci.iSubItem = 1;
ci.cx = 128;
ci.fmt = LVCFMT_CENTER;
ci.pszText = (WCHAR *)(const WCHAR *)s;
ci.iSubItem = 1;
_listView.InsertColumn(1, &ci);
#if NUM_EXT_GROUPS > 1
{
LangString(IDS_SYSTEM_ALL_USERS, s);
ci.pszText = (WCHAR *)(const WCHAR *)s;
ci.iSubItem = 2;
ci.pszText = (LPTSTR)TEXT("All Users");
_listView.InsertColumn(2, &ci);
}
#endif

View File

@@ -40,7 +40,7 @@ struct CModifiedExtInfo: public NRegistryAssoc::CShellExtInfo
Other = true;
if (IsIt7Zip())
{
Other7Zip = !iconPath.IsEqualToNoCase(IconPath);
Other7Zip = !iconPath.IsEqualTo_NoCase(IconPath);
if (!Other7Zip)
{
State = kExtState_7Zip;

View File

@@ -1,18 +1,18 @@
#include "SystemPageRes.h"
#include "../../GuiCommon.rc"
#define xc 200
#define yc 250
#define xc 240
#define yc 252
IDD_SYSTEM DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT
CAPTION "System"
BEGIN
LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8
PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 72, m + 12, 40, bys
PUSHBUTTON "+", IDB_SYSTEM_ALL, 140, m + 12, 40, bys
PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 80, m + 12, 40, bys
PUSHBUTTON "+", IDB_SYSTEM_ALL, 166, m + 12, 40, bys
CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32",
LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
m, m + 32, xc, (yc - m - 32 - 1)
m, m + 32, xc, (yc - 32)
END
#ifdef UNDER_CE
@@ -32,7 +32,12 @@ BEGIN
PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 60, m + 12, 40, bys
CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32",
LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
m, m + 32, xc, (yc - m - 32 - 1 - 8)
m, m + 32, xc, (yc - 32)
END
#endif
STRINGTABLE
BEGIN
IDS_SYSTEM_ALL_USERS "All users"
END

View File

@@ -2,6 +2,7 @@
#define IDD_SYSTEM_2 12200
#define IDT_SYSTEM_ASSOCIATE 2201
#define IDS_SYSTEM_ALL_USERS 2202
#define IDL_SYSTEM_ASSOCIATE 100
#define IDB_SYSTEM_CURRENT 101

View File

@@ -185,6 +185,6 @@ void CPairsStorage::SaveToString(UString &text) const
text += L' ';
text += pair.Value;
text += L'\x0D';
text += L'\n';
text.Add_LF();
}
}

View File

@@ -19,7 +19,7 @@ class CPairsStorage
int FindID(const UString &id) const;
void Sort();
public:
void Clear() { Pairs.Clear(); };
void Clear() { Pairs.Clear(); }
bool ReadFromString(const UString &text);
void SaveToString(UString &text) const;

View File

@@ -2,13 +2,27 @@
#include "StdAfx.h"
#include "PasswordDialog.h"
#include "../../../Windows/ErrorMsg.h"
#include "../GUI/resource3.h"
#include "LangUtils.h"
#include "UpdateCallback100.h"
STDMETHODIMP CUpdateCallback100Imp::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 /* isDir */)
{
return ProgressDialog->Sync.ScanProgress(numFiles, totalSize, us2fs(path));
}
STDMETHODIMP CUpdateCallback100Imp::ScanError(const wchar_t *path, HRESULT errorCode)
{
ProgressDialog->Sync.AddError_Code_Name(errorCode, path);
return S_OK;
}
STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles)
{
ProgressDialog->Sync.Set_NumFilesTotal(numFiles);
return S_OK;
return ProgressDialog->Sync.Set_NumFilesTotal(numFiles);
}
STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size)
@@ -30,35 +44,63 @@ STDMETHODIMP CUpdateCallback100Imp::SetRatioInfo(const UInt64 *inSize, const UIn
STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t *name)
{
ProgressDialog->Sync.Set_FilePath(name);
return S_OK;
return SetOperation_Base(NUpdateNotifyOp::kAdd, name, false);
}
STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t *name)
{
ProgressDialog->Sync.Set_FilePath(name);
return S_OK;
return SetOperation_Base(NUpdateNotifyOp::kDelete, name, false);
}
STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* operationResult */)
{
ProgressDialog->Sync.Set_NumFilesCur(++_numFiles);
ProgressDialog->Sync.Set_NumFilesCur(++NumFiles);
return S_OK;
}
void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s);
HRESULT CUpdateCallback100Imp::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
{
if (opRes != NArchive::NExtract::NOperationResult::kOK)
{
UString s;
SetExtractErrorMessage(opRes, isEncrypted, name, s);
ProgressDialog->Sync.AddError_Message(s);
}
return S_OK;
}
HRESULT CUpdateCallback100Imp::ReportUpdateOperation(UInt32 notifyOp, const wchar_t *name, Int32 isDir)
{
return SetOperation_Base(notifyOp, name, IntToBool(isDir));
}
STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message)
{
ProgressDialog->Sync.AddError_Message(message);
return S_OK;
}
HRESULT CUpdateCallback100Imp::OpenFileError(const wchar_t *path, HRESULT errorCode)
{
ProgressDialog->Sync.AddError_Code_Name(errorCode, path);
return S_OK;
}
STDMETHODIMP CUpdateCallback100Imp::ReadingFileError(const wchar_t *path, HRESULT errorCode)
{
ProgressDialog->Sync.AddError_Code_Name(errorCode, path);
return S_OK;
}
STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
*password = NULL;
*passwordIsDefined = BoolToInt(_passwordIsDefined);
if (!_passwordIsDefined)
*passwordIsDefined = BoolToInt(PasswordIsDefined);
if (!PasswordIsDefined)
return S_OK;
return StringToBstr(_password, password);
return StringToBstr(Password, password);
}
STDMETHODIMP CUpdateCallback100Imp::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
@@ -74,14 +116,9 @@ STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 * /* files */, con
STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password)
{
*password = NULL;
if (!_passwordIsDefined)
if (!PasswordIsDefined)
{
CPasswordDialog dialog;
ProgressDialog->WaitCreating();
if (dialog.Create(*ProgressDialog) != IDOK)
return E_ABORT;
_password = dialog.Password;
_passwordIsDefined = true;
RINOK(ShowAskPasswordDialog())
}
return StringToBstr(_password, password);
return StringToBstr(Password, password);
}

View File

@@ -9,26 +9,29 @@
#include "../Agent/IFolderArchive.h"
#include "../GUI/UpdateCallbackGUI2.h"
#include "ProgressDialog2.h"
class CUpdateCallback100Imp:
public IFolderArchiveUpdateCallback,
public IFolderArchiveUpdateCallback2,
public IFolderScanProgress,
public ICryptoGetTextPassword2,
public ICryptoGetTextPassword,
public IArchiveOpenCallback,
public ICompressProgressInfo,
public CUpdateCallbackGUI2,
public CMyUnknownImp
{
bool _passwordIsDefined;
UString _password;
UInt64 _numFiles;
public:
CProgressDialog *ProgressDialog;
CUpdateCallback100Imp(): ProgressDialog(0) {}
// CUpdateCallback100Imp() {}
MY_UNKNOWN_IMP5(
MY_UNKNOWN_IMP7(
IFolderArchiveUpdateCallback,
IFolderArchiveUpdateCallback2,
IFolderScanProgress,
ICryptoGetTextPassword2,
ICryptoGetTextPassword,
IArchiveOpenCallback,
@@ -37,18 +40,13 @@ public:
INTERFACE_IProgress(;)
INTERFACE_IArchiveOpenCallback(;)
INTERFACE_IFolderArchiveUpdateCallback(;)
INTERFACE_IFolderArchiveUpdateCallback2(;)
INTERFACE_IFolderScanProgress(;)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
void Init(bool passwordIsDefined, const UString &password)
{
_passwordIsDefined = passwordIsDefined;
_password = password;
_numFiles = 0;
}
};
#endif

View File

@@ -302,7 +302,7 @@ void ReadCopyHistory(UStringVector &folders)
void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s)
{
for (unsigned i = 0; i < list.Size();)
if (s.IsEqualToNoCase(list[i]))
if (s.IsEqualTo_NoCase(list[i]))
list.Delete(i);
else
i++;

View File

@@ -97,6 +97,7 @@ EXPLORER_OBJS = \
GUI_OBJS = \
$O\HashGUI.obj \
$O\UpdateCallbackGUI2.obj \
COMPRESS_OBJS = \
$O\CopyCoder.obj \

View File

@@ -45,6 +45,7 @@
#define IDM_CREATE_FILE 556
// #define IDM_EXIT 557
#define IDM_LINK 558
#define IDM_ALT_STREAMS 559
#define IDM_SELECT_ALL 600
#define IDM_DESELECT_ALL 601

View File

@@ -48,6 +48,7 @@ BEGIN
MENUITEM "Create File\tCtrl+N", IDM_CREATE_FILE
MENUITEM SEPARATOR
MENUITEM "&Link...", IDM_LINK
MENUITEM "&Alternate streams", IDM_ALT_STREAMS
MENUITEM SEPARATOR
MENUITEM "E&xit\tAlt+F4", IDCLOSE
END
@@ -252,5 +253,6 @@ END
#include "SplitDialog.rc"
#include "SystemPage.rc"
#include "../GUI/Extract.rc"
#include "../GUI/resource3.rc"
#include "../Explorer/resource2.rc"
#include "resourceGui.rc"