From 585698650f7257d2cefa6a3a2a49d5bbe84fd9b2 Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Thu, 22 Jul 2021 23:00:14 +0100 Subject: 21.02 --- CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp | 232 ++++++++++++++++++++--- 1 file changed, 203 insertions(+), 29 deletions(-) (limited to 'CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp') diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp index 4e964628..a7873fe5 100644 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp @@ -8,10 +8,14 @@ #include "../../../Windows/Thread.h" #include "../Agent/Agent.h" +#include "../GUI/ExtractRes.h" +#include "FileFolderPluginOpen.h" +#include "FormatUtils.h" #include "LangUtils.h" #include "OpenCallback.h" #include "PluginLoader.h" +#include "PropertyName.h" #include "RegistryPlugins.h" using namespace NWindows; @@ -69,18 +73,165 @@ static void SplitNameToPureNameAndExtension(const FString &fullName, { pureName.SetFrom(fullName, index); extensionDelimiter = '.'; - extension = fullName.Ptr(index + 1); + extension = fullName.Ptr((unsigned)index + 1); } } -HRESULT OpenFileFolderPlugin( - IInStream *inStream, - const FString &path, - const UString &arcFormat, - HMODULE *module, - IFolderFolder **resultFolder, - HWND parentWindow, - bool &encrypted, UString &password) + +struct CArcLevelInfo +{ + UString Error; + UString Path; + UString Type; + UString ErrorType; + UString ErrorFlags; +}; + + +struct CArcLevelsInfo +{ + CObjectVector Levels; // LastLevel Is NON-OPEN +}; + + +UString GetOpenArcErrorMessage(UInt32 errorFlags); + + +static void GetFolderLevels(CMyComPtr &folder, CArcLevelsInfo &levels) +{ + levels.Levels.Clear(); + + CMyComPtr getFolderArcProps; + folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps); + + if (!getFolderArcProps) + return; + CMyComPtr arcProps; + getFolderArcProps->GetFolderArcProps(&arcProps); + if (!arcProps) + return; + + UInt32 numLevels; + if (arcProps->GetArcNumLevels(&numLevels) != S_OK) + numLevels = 0; + + for (UInt32 level = 0; level <= numLevels; level++) + { + const PROPID propIDs[] = { kpidError, kpidPath, kpidType, kpidErrorType }; + + CArcLevelInfo lev; + + for (Int32 i = 0; i < 4; i++) + { + CMyComBSTR name; + NCOM::CPropVariant prop; + if (arcProps->GetArcProp(level, propIDs[i], &prop) != S_OK) + continue; + if (prop.vt != VT_EMPTY) + { + UString *s = NULL; + switch (propIDs[i]) + { + case kpidError: s = &lev.Error; break; + case kpidPath: s = &lev.Path; break; + case kpidType: s = &lev.Type; break; + case kpidErrorType: s = &lev.ErrorType; break; + } + *s = (prop.vt == VT_BSTR) ? prop.bstrVal : L"?"; + } + } + + { + NCOM::CPropVariant prop; + if (arcProps->GetArcProp(level, kpidErrorFlags, &prop) == S_OK) + { + UInt32 flags = GetOpenArcErrorFlags(prop); + if (flags != 0) + lev.ErrorFlags = GetOpenArcErrorMessage(flags); + } + } + + levels.Levels.Add(lev); + } +} + +static UString GetBracedType(const wchar_t *type) +{ + UString s ('['); + s += type; + s += ']'; + return s; +} + +static void GetFolderError(CMyComPtr &folder, UString &open_Errors, UString &nonOpen_Errors) +{ + CArcLevelsInfo levs; + GetFolderLevels(folder, levs); + open_Errors.Empty(); + nonOpen_Errors.Empty(); + + FOR_VECTOR (i, levs.Levels) + { + bool isNonOpenLevel = (i == 0); + const CArcLevelInfo &lev = levs.Levels[levs.Levels.Size() - 1 - i]; + + UString m; + + if (!lev.ErrorType.IsEmpty()) + { + m = MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(lev.ErrorType)); + if (!isNonOpenLevel) + { + m.Add_LF(); + m += MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(lev.Type)); + } + } + + if (!lev.Error.IsEmpty()) + { + if (!m.IsEmpty()) + m.Add_LF(); + m += GetBracedType(lev.Type); + m += " : "; + m += GetNameOfProperty(kpidError, L"Error"); + m += " : "; + m += lev.Error; + } + + if (!lev.ErrorFlags.IsEmpty()) + { + if (!m.IsEmpty()) + m.Add_LF(); + m += GetNameOfProperty(kpidErrorFlags, L"Errors"); + m += ": "; + m += lev.ErrorFlags; + } + + if (!m.IsEmpty()) + { + if (isNonOpenLevel) + { + UString &s = nonOpen_Errors; + s += lev.Path; + s.Add_LF(); + s += m; + } + else + { + UString &s = open_Errors; + if (!s.IsEmpty()) + s += "--------------------\n"; + s += lev.Path; + s.Add_LF(); + s += m; + } + } + } +} + + +HRESULT CFfpOpen::OpenFileFolderPlugin(IInStream *inStream, + const FString &path, const UString &arcFormat, HWND parentWindow) { CObjectVector plugins; ReadFileFolderPluginInfoList(plugins); @@ -92,8 +243,8 @@ HRESULT OpenFileFolderPlugin( FString fileName; if (slashPos >= 0) { - dirPrefix.SetFrom(path, slashPos + 1); - fileName = path.Ptr(slashPos + 1); + dirPrefix.SetFrom(path, (unsigned)(slashPos + 1)); + fileName = path.Ptr((unsigned)(slashPos + 1)); } else fileName = path; @@ -120,6 +271,8 @@ HRESULT OpenFileFolderPlugin( } */ + ErrorMessage.Empty(); + FOR_VECTOR (i, plugins) { const CPluginInfo &plugin = plugins[i]; @@ -136,24 +289,29 @@ HRESULT OpenFileFolderPlugin( t.OpenCallbackSpec = new COpenArchiveCallback; t.OpenCallback = t.OpenCallbackSpec; - t.OpenCallbackSpec->PasswordIsDefined = encrypted; - t.OpenCallbackSpec->Password = password; + t.OpenCallbackSpec->PasswordIsDefined = Encrypted; + t.OpenCallbackSpec->Password = Password; t.OpenCallbackSpec->ParentWindow = parentWindow; if (inStream) t.OpenCallbackSpec->SetSubArchiveName(fs2us(fileName)); else - t.OpenCallbackSpec->LoadFileInfo(dirPrefix, fileName); + { + RINOK(t.OpenCallbackSpec->LoadFileInfo2(dirPrefix, fileName)); + } t.InStream = inStream; t.Path = fs2us(path); t.ArcFormat = arcFormat; - UString progressTitle = LangString(IDS_OPENNING); - t.OpenCallbackSpec->ProgressDialog.MainWindow = parentWindow; - t.OpenCallbackSpec->ProgressDialog.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE); - t.OpenCallbackSpec->ProgressDialog.MainAddTitle = progressTitle + L' '; - t.OpenCallbackSpec->ProgressDialog.WaitMode = true; + const UString progressTitle = LangString(IDS_OPENNING); + { + CProgressDialog &pd = t.OpenCallbackSpec->ProgressDialog; + pd.MainWindow = parentWindow; + pd.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE); + pd.MainAddTitle = progressTitle + L' '; + pd.WaitMode = true; + } { NWindows::CThread thread; @@ -161,23 +319,39 @@ HRESULT OpenFileFolderPlugin( t.OpenCallbackSpec->StartProgressDialog(progressTitle, thread); } - if (t.Result == E_ABORT) + if (t.Result != S_FALSE && t.Result != S_OK) return t.Result; - encrypted = t.OpenCallbackSpec->PasswordIsDefined; - if (t.Result == S_OK) + if (t.Folder) { - // if (openCallbackSpec->PasswordWasAsked) + UString open_Errors, nonOpen_Errors; + GetFolderError(t.Folder, open_Errors, nonOpen_Errors); + if (!nonOpen_Errors.IsEmpty()) { - password = t.OpenCallbackSpec->Password; + ErrorMessage = nonOpen_Errors; + // if (t.Result != S_OK) return t.Result; + /* if there are good open leves, and non0open level, + we could force error as critical error and return error here + but it's better to allow to open such rachives */ + // return S_FALSE; } - *module = library.Detach(); - *resultFolder = t.Folder.Detach(); - return S_OK; + } + + // if (openCallbackSpec->PasswordWasAsked) + { + Encrypted = t.OpenCallbackSpec->PasswordIsDefined; + Password = t.OpenCallbackSpec->Password; + } + + if (t.Result == S_OK) + { + Library.Attach(library.Detach()); + // Folder.Attach(t.Folder.Detach()); + Folder = t.Folder; } - if (t.Result != S_FALSE) - return t.Result; + return t.Result; } + return S_FALSE; } -- cgit v1.2.3