diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2015-06-15 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:16:54 +0300 |
commit | 54490d51d5c6b0d794dcbad2d634d4c95fc25b6c (patch) | |
tree | c3c413656432c0ef87b2841c80e42b55ad17d4e8 /CPP/7zip/UI/FileManager | |
parent | 0713a3ab803e57401f18432148b4139e5fe6e5dd (diff) |
15.0515.05
Diffstat (limited to 'CPP/7zip/UI/FileManager')
69 files changed, 3368 insertions, 1351 deletions
diff --git a/CPP/7zip/UI/FileManager/AboutDialog.cpp b/CPP/7zip/UI/FileManager/AboutDialog.cpp index 10d76671..35e67753 100644 --- a/CPP/7zip/UI/FileManager/AboutDialog.cpp +++ b/CPP/7zip/UI/FileManager/AboutDialog.cpp @@ -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 diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp new file mode 100644 index 00000000..c209bf35 --- /dev/null +++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp @@ -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; +} + +} diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.h b/CPP/7zip/UI/FileManager/AltStreamsFolder.h new file mode 100644 index 00000000..ccd0a58f --- /dev/null +++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.h @@ -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 diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp index 51c8d2db..b6a66975 100644 --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -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; } - else + + bool destIsFsPath = false; + + if (possibleToUseDestPanel) { - if (!IsCorrectFsName(destPath)) + if (destPanel.IsFSFolder() || destPanel.IsAltStreamsFolder()) + destIsFsPath = true; + else if (destPanel.IsFSDrivesFolder() || destPanel.IsRootFolder()) { - srcPanel.MessageBoxError(E_INVALIDARG); + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } - int pos = destPath.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos >= 0) + } + else + { + if (IsAltPathPrefix(us2fs(destPath))) { - UString prefix = destPath.Left(pos + 1); - CreateComplexDir(us2fs(prefix)); - if (!CheckFolderPath(prefix)) + // we allow alt streams dest only to alt stream folder in second panel + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); + return; + /* + 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(); } diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index c775cc2e..5fe95e0b 100644 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -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(); } diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp index 32db8f8f..89a6b45a 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -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; } diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.h b/CPP/7zip/UI/FileManager/BrowseDialog.h index 77c749b5..957af2e2 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog.h +++ b/CPP/7zip/UI/FileManager/BrowseDialog.h @@ -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 */ diff --git a/CPP/7zip/UI/FileManager/EditPage.rc b/CPP/7zip/UI/FileManager/EditPage.rc index f5618d04..38f74ea1 100644 --- a/CPP/7zip/UI/FileManager/EditPage.rc +++ b/CPP/7zip/UI/FileManager/EditPage.rc @@ -1,7 +1,7 @@ #include "EditPageRes.h" #include "../../GuiCommon.rc" -#define xc 200 +#define xc 240 #define yc 80 IDD_EDIT MY_PAGE diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp index ed4bb884..50c43163 100644 --- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp +++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp @@ -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,101 +232,108 @@ 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::kOK: + 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: - { - 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; - } + messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR; + break; + */ + } - UString msg; - UString msgOld; + UString msg; + UString msgOld; - #ifndef _SFX - if (id != 0) - LangString_OnlyFromLangFile(id, msg); - if (messageID != 0 && msg.IsEmpty()) - LangString_OnlyFromLangFile(messageID, msgOld); - #endif + #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 (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) - { - // s += L" : "; - // s += LangString(IDS_EXTRACT_MSG_ENCRYPTED); - s += L" : "; - s += LangString(IDS_EXTRACT_MSG_WRONG_PSW); - } - s += L" : "; - s += _currentFilePath; - } + 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) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + default: + { + UString s; + 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,76 +452,153 @@ 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 (_needWriteArchivePath) + if (errorFlags != 0) + AddNewLineString(s, GetOpenArcErrorMessage(errorFlags)); + + if (!er.ErrorMessage.IsEmpty()) + AddNewLineString(s, er.ErrorMessage); + + if (warningFlags != 0) { - if (!_currentArchivePath.IsEmpty()) - AddError_Message(_currentArchivePath); - _needWriteArchivePath = false; + s += GetNameOfProperty(kpidWarningFlags, L"Warnings"); + s.AddAscii(":"); + s.Add_LF(); + AddNewLineString(s, GetOpenArcErrorMessage(warningFlags)); } - - if (level != 0) + + if (!er.WarningMessage.IsEmpty()) { - UString s; - s += name; - s += L": "; - MessageError(s); + s += GetNameOfProperty(kpidWarning, L"Warning"); + s.AddAscii(": "); + s += er.WarningMessage; + s.Add_LF(); } +} - if (errorFlags != 0) - MessageError(GetOpenArcErrorMessage(errorFlags)); +static UString GetBracedType(const wchar_t *type) +{ + UString s = L'['; + s += type; + s += L']'; + return s; +} - if (errors && wcslen(errors) != 0) - MessageError(errors); +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 (warningFlags != 0) - MessageError((UString)L"Warnings: " + GetOpenArcErrorMessage(warningFlags)); + if (!er.IsThereErrorOrWarning() && er.ErrorFormatIndex < 0) + continue; - if (warnings && wcslen(warnings) != 0) - MessageError((UString)L"Warnings: " + warnings); + if (s.IsEmpty()) + { + s += name; + s.Add_LF(); + } + + if (level != 0) + { + AddNewLineString(s, arc.Path); + } + + ErrorInfo_Print(s, er); - return S_OK; -} + 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)))); + } + } + } -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) + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result != S_OK) { - s += L"The archive is open with offset"; + 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); } - else + + 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()) { - 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"; + NumArchiveErrors++; + AddError_Message(s); + _needWriteArchivePath = false; } - MessageError(s); - NumArchiveErrors++; + return S_OK; } - + HRESULT CExtractCallbackImp::ThereAreNoFiles() { return S_OK; } +void CExtractCallbackImp::Add_ArchiveName_Error() +{ + if (_needWriteArchivePath) + { + if (!_currentArchivePath.IsEmpty()) + AddError_Message(_currentArchivePath); + _needWriteArchivePath = false; + } +} + HRESULT CExtractCallbackImp::ExtractResult(HRESULT result) { if (result == S_OK) @@ -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)) diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h index 71e48e5e..1654bcd6 100644 --- a/CPP/7zip/UI/FileManager/ExtractCallback.h +++ b/CPP/7zip/UI/FileManager/ExtractCallback.h @@ -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), diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp index 537103ae..00b152c8 100644 --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -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: { diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp index 4a7f16a6..f18e5441 100644 --- a/CPP/7zip/UI/FileManager/FM.dsp +++ b/CPP/7zip/UI/FileManager/FM.dsp @@ -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" diff --git a/CPP/7zip/UI/FileManager/FM.mak b/CPP/7zip/UI/FileManager/FM.mak index 234a5920..6a85ea2f 100644 --- a/CPP/7zip/UI/FileManager/FM.mak +++ b/CPP/7zip/UI/FileManager/FM.mak @@ -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 \ diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp index 84639de7..69f89325 100644 --- a/CPP/7zip/UI/FileManager/FSDrives.cpp +++ b/CPP/7zip/UI/FileManager/FSDrives.cpp @@ -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; } diff --git a/CPP/7zip/UI/FileManager/FSDrives.h b/CPP/7zip/UI/FileManager/FSDrives.h index a8e25d7d..f12e4da8 100644 --- a/CPP/7zip/UI/FileManager/FSDrives.h +++ b/CPP/7zip/UI/FileManager/FSDrives.h @@ -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; } }; diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index a27066c3..e46afb9e 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp @@ -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); diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h index cb0d4ec2..057ba14c 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.h +++ b/CPP/7zip/UI/FileManager/FSFolder.h @@ -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 diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp index 3f2fc9af..54dabc57 100644 --- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -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,110 +194,152 @@ typedef BOOL (WINAPI * CopyFileExPointerW)( IN DWORD dwCopyFlags ); -static bool FsCopyFile(CFSTR oldFile, CFSTR newFile, IProgress *progress, UInt64 &completedSize) +typedef BOOL (WINAPI * Func_MoveFileWithProgressW)( + IN LPCWSTR lpExistingFileName, + IN LPCWSTR lpNewFileName, + IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, + IN LPVOID lpData OPTIONAL, + IN DWORD dwFlags + ); + +struct CCopyState { - CProgressInfo progressInfo; - progressInfo.Progress = progress; - progressInfo.StartPos = completedSize; - BOOL CancelFlag = FALSE; + CProgressInfo ProgressInfo; + IFolderOperationsExtractCallback *Callback; + UInt64 TotalSize; + bool MoveMode; + bool UseReadWriteMode; + + Func_CopyFileExW my_CopyFileExW; + #ifndef UNDER_CE + Func_MoveFileWithProgressW my_MoveFileWithProgressW; + #endif #ifndef _UNICODE - if (g_IsNT) + 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) { - const wchar_t *k_DllName = - #ifdef UNDER_CE + my_CopyFileExA = (Func_CopyFileExA)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "CopyFileExA"); + } + else + #endif + { + HMODULE module = ::GetModuleHandleW( + #ifdef UNDER_CE L"coredll.dll" - #else + #else L"kernel32.dll" - #endif - ; - CopyFileExPointerW copyFunctionW = (CopyFileExPointerW) - My_GetProcAddress(::GetModuleHandleW(k_DllName), "CopyFileExW"); - + #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 (copyFunctionW == 0) - return BOOLToBool(::CopyFileW(fs2us(oldFile), fs2us(newFile), TRUE)); - if (copyFunctionW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine, - &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + if (CopyFile_NT(fs2us(oldFile), fs2us(newFile))) return true; } #ifdef WIN_LONG_PATH if (USE_SUPER_PATH_2) { - UString longPathExisting, longPathNew; - if (!GetSuperPaths(oldFile, newFile, longPathExisting, longPathNew, USE_MAIN_PATH_2)) + if (IsCallbackProgressError()) + return false; + UString superPathOld, superPathNew; + if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2)) return false; - if (copyFunctionW(longPathExisting, longPathNew, CopyProgressRoutine, - &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + if (CopyFile_NT(superPathOld, superPathNew)) 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)( - IN LPCWSTR lpExistingFileName, - IN LPCWSTR lpNewFileName, - IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, - IN LPVOID lpData OPTIONAL, - IN DWORD dwFlags - ); - -#ifdef UNDER_CE -#define NON_CE_VAR(_v_) -#else -#define NON_CE_VAR(_v_) _v_ -#endif - -static bool FsMoveFile(CFSTR oldFile, CFSTR newFile, - IProgress * NON_CE_VAR(progress), - UInt64 & NON_CE_VAR(completedSize)) +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; + UString superPathOld, superPathNew; + if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2)) return false; - if (moveFunction(longPathExisting, longPathNew, CopyProgressRoutine, - &progressInfo, MOVEFILE_COPY_ALLOWED)) + 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) - { - 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)) - { - RINOK(SendMessageError(callback, "can not move to file: ", destPathNew)); - } - } - 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)) + if (state.MoveMode) { - RINOK(SendMessageError(callback, "can not create folder: ", destPath)); - return E_ABORT; - } - { - CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK)); - CDirItem fi; - while (enumerator.Next(fi)) + if (!RemoveDir(srcPath)) { - 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)); - } + RINOK(SendMessageError(state.Callback, "can not remove folder", srcPath)); + return E_ABORT; } } - 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; diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp index 2d3b1d92..dc46ff5b 100644 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp @@ -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) diff --git a/CPP/7zip/UI/FileManager/FilePlugins.cpp b/CPP/7zip/UI/FileManager/FilePlugins.cpp index 556c54fd..46000301 100644 --- a/CPP/7zip/UI/FileManager/FilePlugins.cpp +++ b/CPP/7zip/UI/FileManager/FilePlugins.cpp @@ -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; } diff --git a/CPP/7zip/UI/FileManager/FoldersPage.rc b/CPP/7zip/UI/FileManager/FoldersPage.rc index fb48ee6e..cb345ea6 100644 --- a/CPP/7zip/UI/FileManager/FoldersPage.rc +++ b/CPP/7zip/UI/FileManager/FoldersPage.rc @@ -1,7 +1,7 @@ #include "FoldersPageRes.h" #include "../../GuiCommon.rc" -#define xc 196 +#define xc 240 #define yc 100 IDD_FOLDERS MY_PAGE diff --git a/CPP/7zip/UI/FileManager/IFolder.h b/CPP/7zip/UI/FileManager/IFolder.h index 60991a71..c5cff06e 100644 --- a/CPP/7zip/UI/FileManager/IFolder.h +++ b/CPP/7zip/UI/FileManager/IFolder.h @@ -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; \ diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp index 54253295..d9dc6c52 100644 --- a/CPP/7zip/UI/FileManager/LangPage.cpp +++ b/CPP/7zip/UI/FileManager/LangPage.cpp @@ -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); } diff --git a/CPP/7zip/UI/FileManager/LangPage.rc b/CPP/7zip/UI/FileManager/LangPage.rc index 5aeaf406..164e2d30 100644 --- a/CPP/7zip/UI/FileManager/LangPage.rc +++ b/CPP/7zip/UI/FileManager/LangPage.rc @@ -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 diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp index 15d68f43..9723704a 100644 --- a/CPP/7zip/UI/FileManager/LangUtils.cpp +++ b/CPP/7zip/UI/FileManager/LangUtils.cpp @@ -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; diff --git a/CPP/7zip/UI/FileManager/LangUtils.h b/CPP/7zip/UI/FileManager/LangUtils.h index 509a5ae3..d63a443c 100644 --- a/CPP/7zip/UI/FileManager/LangUtils.h +++ b/CPP/7zip/UI/FileManager/LangUtils.h @@ -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 diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp index a24ec601..bc482e4b 100644 --- a/CPP/7zip/UI/FileManager/LinkDialog.cpp +++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp @@ -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; diff --git a/CPP/7zip/UI/FileManager/MenuPage.rc b/CPP/7zip/UI/FileManager/MenuPage.rc index 626f415e..f20c574e 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.rc +++ b/CPP/7zip/UI/FileManager/MenuPage.rc @@ -1,7 +1,7 @@ #include "MenuPageRes.h" #include "../../GuiCommon.rc" -#define xc 196 +#define xc 240 #define yc 196 IDD_MENU MY_PAGE diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp index 401e48ef..b0f6615e 100644 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp @@ -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; } diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.h b/CPP/7zip/UI/FileManager/MyLoadMenu.h index 53e9d0ef..02569e52 100644 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.h +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.h @@ -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 diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp index f3d531ab..bfccc353 100644 --- a/CPP/7zip/UI/FileManager/NetFolder.cpp +++ b/CPP/7zip/UI/FileManager/NetFolder.cpp @@ -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); diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp index a657bc90..c6feb902 100644 --- a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp @@ -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); diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index d63bdc17..a7416a4c 100644 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -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(); } */ diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index dc293729..39915a27 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -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,37 +609,35 @@ public: class CDisableTimerProcessing { - bool _processTimerMem; - - CPanel &_panel; + CLASS_NO_COPY(CDisableTimerProcessing); - CDisableTimerProcessing(const CDisableTimerProcessing &); - CDisableTimerProcessing& operator=(const CDisableTimerProcessing &); + bool _processTimer; + CPanel &_panel; + 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); - CPanel &_panel; + bool _processNotify; + bool _processStatusBar; - CDisableNotify(const CDisableNotify &); - CDisableNotify& operator=(const CDisableNotify &); + CPanel &_panel; public: @@ -612,20 +645,20 @@ public: ~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); diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp index d11368cf..fb418963 100644 --- a/CPP/7zip/UI/FileManager/PanelCopy.cpp +++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp @@ -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 */ + + /* + #ifdef EXTERNAL_CODECS + ThrowException_if_Error(LoadGlobalCodecs()); + #endif + */ - extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS options.hashMethods); + 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; diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp index ab93ecba..3b0ee052 100644 --- a/CPP/7zip/UI/FileManager/PanelCrc.cpp +++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp @@ -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); + } } diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp index 9434d156..e20ddd63 100644 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -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; } diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index 83993bb1..cd70c727 100644 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -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 (;;) - { - CMyComPtr<IFolderFolder> newFolder; - HRESULT res = _folder->BindToParentFolder(&newFolder); - if (!newFolder || res != S_OK) - break; - SetNewFolder(newFolder); - } - UStringVector parts; - SplitPathToParts(fullPath.Ptr(virtPath.Len()), parts); - FOR_VECTOR (i, parts) + 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)) { - 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); + path = relatPath.Ptr(foldPath.Len()); + break; } - return S_OK; + 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; } - CloseOpenFolders(); - UString sysPath = fullPath; - CFileInfo fileInfo; - UStringVector reducedParts; - while (!sysPath.IsEmpty()) + if (_parentFolders.IsEmpty()) { - if (fileInfo.Find(us2fs(sysPath))) - break; - int pos = sysPath.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos < 0) + // ---------- 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 + { + /* + 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 { - if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1) - reducedParts.Add(sysPath.Ptr(pos + 1)); - sysPath.DeleteFrom(pos); + 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); + } } - } - 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) + if (newFolder) + { SetNewFolder(newFolder); + // LoadFullPath(); + return S_OK; + } } - else + { - FString dirPrefix, fileName; - NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName); - if (_folder->BindToFolder(fs2us(dirPrefix), &newFolder) == S_OK) + // ---------- we open folder remPath in archive and sub archives ---------- + + for (unsigned curPos = 0; curPos != path.Len();) { - 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) - { - RINOK(res); - } - /* - if (res == E_ABORT) - return res; - */ - if (res == S_OK) + 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) { - 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::CloseOpenFolders() +void CPanel::CloseOneLevel() { - while (_parentFolders.Size() > 0) + ReleaseFolder(); + _library.Free(); { - ReleaseFolder(); - _library.Free(); - SetNewFolder(_parentFolders.Back().ParentFolder); - _library.Attach(_parentFolders.Back().Library.Detach()); - if (_parentFolders.Size() > 1) - OpenParentArchiveFolder(); - _parentFolders.DeleteBack(); + 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.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 +} diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index d9beedb8..a485522f 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -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; diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp index 8d74b8cd..491a36ad 100644 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp @@ -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); } } } diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp index 7be6aa62..2f37db14 100644 --- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp @@ -19,30 +19,57 @@ using namespace NWindows; -static void ConvertSizeToString(UInt64 value, wchar_t *dest) +#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); + +static void ConvertSizeToString(UInt64 val, wchar_t *s) throw() { - char s[32]; - ConvertUInt64ToString(value, s); - unsigned i = MyStringLen(s); - unsigned pos = ARRAY_SIZE(s); - s[--pos] = 0; - while (i > 3) + unsigned char temp[32]; + unsigned i = 0; + + if (val <= (UInt32)0xFFFFFFFF) + { + UInt32 val32 = (UInt32)val; + INT_TO_STR_SPEC(val32) + } + else { - s[--pos] = s[--i]; - s[--pos] = s[--i]; - s[--pos] = s[--i]; - s[--pos] = L' '; + INT_TO_STR_SPEC(val) } - while (i > 0) - s[--pos] = s[--i]; - for (;;) + if (i < 3) { - char c = s[pos++]; - *dest++ = (unsigned char)c; - if (c == 0) - break; + 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; } +*/ -LRESULT CPanel::SetItemText(LVITEMW &item) +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; } diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index d7108204..5a527cb4 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -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)); diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp index 28c945e5..62a08e13 100644 --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -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) diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp index a40997c2..7b53eb00 100644 --- a/CPP/7zip/UI/FileManager/PanelSelect.cpp +++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp @@ -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; } diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp index fe5d3ffd..82d6756e 100644 --- a/CPP/7zip/UI/FileManager/PanelSort.cpp +++ b/CPP/7zip/UI/FileManager/PanelSort.cpp @@ -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); } diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp index ce15fcc5..a8c0d352 100644 --- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -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); diff --git a/CPP/7zip/UI/FileManager/PluginInterface.h b/CPP/7zip/UI/FileManager/PluginInterface.h index 3ce5fa8e..37654a03 100644 --- a/CPP/7zip/UI/FileManager/PluginInterface.h +++ b/CPP/7zip/UI/FileManager/PluginInterface.h @@ -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) diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp index c9ca3942..231d0ace 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -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); diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h index ea1559a7..03f836da 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h @@ -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) {} diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc index 43c4584f..8b8c7899 100644 --- a/CPP/7zip/UI/FileManager/PropertyName.rc +++ b/CPP/7zip/UI/FileManager/PropertyName.rc @@ -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 diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h index 199aa6da..3696ed2e 100644 --- a/CPP/7zip/UI/FileManager/PropertyNameRes.h +++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h @@ -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 diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp index ee944350..93ba40c2 100644 --- a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp +++ b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp @@ -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) diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp index 234c51dd..c5b57821 100644 --- a/CPP/7zip/UI/FileManager/RootFolder.cpp +++ b/CPP/7zip/UI/FileManager/RootFolder.cpp @@ -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; diff --git a/CPP/7zip/UI/FileManager/RootFolder.h b/CPP/7zip/UI/FileManager/RootFolder.h index e9ef2d8c..e2537837 100644 --- a/CPP/7zip/UI/FileManager/RootFolder.h +++ b/CPP/7zip/UI/FileManager/RootFolder.h @@ -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) diff --git a/CPP/7zip/UI/FileManager/SettingsPage.rc b/CPP/7zip/UI/FileManager/SettingsPage.rc index 3e4a611e..c724fcb7 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.rc +++ b/CPP/7zip/UI/FileManager/SettingsPage.rc @@ -1,7 +1,7 @@ #include "SettingsPageRes.h" #include "../../GuiCommon.rc" -#define xc 200 +#define xc 240 #define yc 120 IDD_SETTINGS MY_PAGE diff --git a/CPP/7zip/UI/FileManager/SplitDialog.cpp b/CPP/7zip/UI/FileManager/SplitDialog.cpp index d35d76c9..d7d14d7c 100644 --- a/CPP/7zip/UI/FileManager/SplitDialog.cpp +++ b/CPP/7zip/UI/FileManager/SplitDialog.cpp @@ -38,7 +38,7 @@ bool CSplitDialog::OnInit() { UString title; GetText(title); - title += L' '; + title.Add_Space(); title += FilePath; SetText(title); } diff --git a/CPP/7zip/UI/FileManager/StringUtils.cpp b/CPP/7zip/UI/FileManager/StringUtils.cpp index fb38a735..10056549 100644 --- a/CPP/7zip/UI/FileManager/StringUtils.cpp +++ b/CPP/7zip/UI/FileManager/StringUtils.cpp @@ -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; } +*/ diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp index a40c4e3d..a7f0c3fb 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.cpp +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp @@ -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 diff --git a/CPP/7zip/UI/FileManager/SystemPage.h b/CPP/7zip/UI/FileManager/SystemPage.h index 0bf6aae7..d38bd1b0 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.h +++ b/CPP/7zip/UI/FileManager/SystemPage.h @@ -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; diff --git a/CPP/7zip/UI/FileManager/SystemPage.rc b/CPP/7zip/UI/FileManager/SystemPage.rc index 42e72cf1..3bb143a4 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.rc +++ b/CPP/7zip/UI/FileManager/SystemPage.rc @@ -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 diff --git a/CPP/7zip/UI/FileManager/SystemPageRes.h b/CPP/7zip/UI/FileManager/SystemPageRes.h index edc576f7..c8944482 100644 --- a/CPP/7zip/UI/FileManager/SystemPageRes.h +++ b/CPP/7zip/UI/FileManager/SystemPageRes.h @@ -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 diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp index 354b479f..0fac2506 100644 --- a/CPP/7zip/UI/FileManager/TextPairs.cpp +++ b/CPP/7zip/UI/FileManager/TextPairs.cpp @@ -185,6 +185,6 @@ void CPairsStorage::SaveToString(UString &text) const text += L' '; text += pair.Value; text += L'\x0D'; - text += L'\n'; + text.Add_LF(); } } diff --git a/CPP/7zip/UI/FileManager/TextPairs.h b/CPP/7zip/UI/FileManager/TextPairs.h index d27cd97c..0a71d044 100644 --- a/CPP/7zip/UI/FileManager/TextPairs.h +++ b/CPP/7zip/UI/FileManager/TextPairs.h @@ -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; diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp index 4141f01d..67e70fb7 100644 --- a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp @@ -2,15 +2,29 @@ #include "StdAfx.h" -#include "PasswordDialog.h" +#include "../../../Windows/ErrorMsg.h" + +#include "../GUI/resource3.h" + +#include "LangUtils.h" #include "UpdateCallback100.h" -STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles) +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.Set_NumFilesTotal(numFiles); + ProgressDialog->Sync.AddError_Code_Name(errorCode, path); return S_OK; } +STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles) +{ + return ProgressDialog->Sync.Set_NumFilesTotal(numFiles); +} + STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size) { ProgressDialog->Sync.Set_NumBytesTotal(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); } diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.h b/CPP/7zip/UI/FileManager/UpdateCallback100.h index 944453a1..7cbc11e3 100644 --- a/CPP/7zip/UI/FileManager/UpdateCallback100.h +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.h @@ -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 diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp index 9688a4a5..2818d0f3 100644 --- a/CPP/7zip/UI/FileManager/ViewSettings.cpp +++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp @@ -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++; diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile index 96ae902f..d9e81780 100644 --- a/CPP/7zip/UI/FileManager/makefile +++ b/CPP/7zip/UI/FileManager/makefile @@ -97,6 +97,7 @@ EXPLORER_OBJS = \ GUI_OBJS = \ $O\HashGUI.obj \ + $O\UpdateCallbackGUI2.obj \ COMPRESS_OBJS = \ $O\CopyCoder.obj \ diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h index 55af3555..23e64edc 100644 --- a/CPP/7zip/UI/FileManager/resource.h +++ b/CPP/7zip/UI/FileManager/resource.h @@ -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 diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc index 61cf33e8..fb57e4f0 100644 --- a/CPP/7zip/UI/FileManager/resource.rc +++ b/CPP/7zip/UI/FileManager/resource.rc @@ -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" |