7zip/CPP/7zip/UI/GUI/UpdateGUI.cpp
Fernando Nillsson Cidade 1eca44e7a7 v2026.3.22.0
English

This patch addresses the review feedback around Windows installer metadata and update-path handling, and removes a partially implemented UI surface that duplicated the existing multi-output path controls.

Installer / ARP metadata
- The installer previously wrote fork-specific hardcoded values into the Windows Uninstall registry entry (`DisplayName`, `DisplayVersion`, `Publisher`).
- That created drift between the installed product metadata and the actual upstream 7-Zip version/author macros used elsewhere in the tree.
- The patch removes the hardcoded fork values and derives the registry values from the existing 7-Zip definitions:
  - `DisplayName` now uses the existing versioned product string (`7-Zip 26.00 (x64)` on 64-bit builds).
  - `DisplayVersion` now comes from `MY_VERSION`.
  - `Publisher` now comes from `MY_AUTHOR_NAME`.
- This makes the Add/Remove Programs entry consistent with the rest of the build metadata and removes the need for manual source edits on each branch-specific release.

Compression dialog cleanup
- The `Paths...` button and its dedicated dialog were not part of the stable workflow.
- At this point the main compression dialog already exposes the supported multi-output behavior through the output-count selector plus the existing archive path rows and browse buttons.
- Keeping a second path-editing dialog in parallel would add maintenance overhead and duplicate UI/state management without providing new functionality.
- For that reason, this patch removes the incomplete/duplicate surface entirely:
  - the `Paths...` button was removed from the dialog resource,
  - the handler declaration/definition was removed,
  - the auxiliary `COutputArcPathsDialog` class was removed,
  - the associated resource IDs and helper parsing/serialization code were removed.
- Functional capability is unchanged: users still configure multiple output targets through the existing archive path controls already present in the compression dialog.

Update path deduplication
- In `UpdateGUI.cpp`, `AddUniquePath()` previously compared paths with a case-sensitive equality check.
- On Windows, this could fail to deduplicate logically identical paths that differ only by casing.
- The comparison is now case-insensitive (`IsEqualTo_NoCase()`), which matches expected Windows path behavior more closely and prevents duplicate item entries in the update/compression path collection stage.
- This is intentionally a minimal fix: it addresses case-only duplication without changing the broader path normalization rules.

Working directory safety
- `PrepareWorkingDirForArchivePath()` previously ignored the return value of `MyGetFullPathName()`.
- If full-path resolution failed, the code could continue with an invalid or empty path and derive an incorrect working directory.
- The function now exits early when `MyGetFullPathName()` fails, leaving `options.WorkingDir` empty.
- This is a conservative change: the downstream update flow already has fallback behavior for an empty working directory, so the patch avoids propagating bad path state without altering the existing fallback model.

Header consistency / non-functional cleanup
- `LangUtils.h` now provides a non-`Z7_LANG` fallback declaration for `LangString_OnlyFromLangFile()`.
- This is not a functional runtime change for normal localized builds, but it keeps the header interface consistent across configurations and avoids IDE/static-analysis mismatches where `Z7_LANG` is not visible to the parser.

Behavioral impact
- No archive format logic was changed.
- No codec behavior was changed.
- No new persistence format was introduced.
- The only runtime behavior changes are:
  - correct Windows ARP metadata,
  - removal of dead/duplicate UI,
  - case-insensitive deduplication of update input paths,
  - safer handling of full-path resolution failure before working directory derivation.

Validation
- The change set was validated with targeted code search and diff review to ensure the removed dialog/button plumbing no longer has remaining references.
- `git diff --check` was also run on the touched files.
- A full build/test pass has not yet been run in this environment.

Portuguese

Este patch responde ao feedback de revisão relacionado aos metadados do instalador no Windows e ao tratamento de caminhos no fluxo de atualização, além de remover uma superfície de UI parcialmente implementada que duplicava os controles já existentes para múltiplos caminhos de saída.

Instalador / metadados do item no Windows
- O instalador estava gravando valores hardcoded e específicos do fork na chave de desinstalação do Windows (`DisplayName`, `DisplayVersion`, `Publisher`).
- Isso criava divergência entre os metadados exibidos em “Aplicativos instalados / Programas e Recursos” e as macros oficiais de versão/autoria já utilizadas no restante do código-fonte.
- O patch remove esses valores fixos do fork e passa a derivar os valores diretamente das definições já existentes do 7-Zip:
  - `DisplayName` agora usa a string versionada já existente do produto (`7-Zip 26.00 (x64)` em builds 64-bit).
  - `DisplayVersion` agora vem de `MY_VERSION`.
  - `Publisher` agora vem de `MY_AUTHOR_NAME`.
- Com isso, a entrada instalada no Windows fica consistente com os demais metadados do build e deixa de exigir edição manual do código a cada release da branch.

Limpeza do diálogo de compressão
- O botão `Paths...` e a dialog auxiliar associada não faziam parte de um fluxo estável/finalizado.
- Neste momento, a janela principal de compressão já expõe o comportamento suportado de múltiplas saídas por meio do seletor de quantidade de saídas, dos campos de caminho de arquivo e dos botões de browse já existentes.
- Manter uma segunda dialog para edição textual desses caminhos aumentaria o custo de manutenção e duplicaria a lógica de estado/UI sem adicionar capacidade funcional nova.
- Por esse motivo, este patch remove completamente essa superfície incompleta/duplicada:
  - o botão `Paths...` foi removido do recurso da dialog,
  - a declaração e a implementação do handler foram removidas,
  - a classe auxiliar `COutputArcPathsDialog` foi removida,
  - os IDs de recurso associados e os helpers internos de parsing/serialização dessa dialog também foram removidos.
- A capacidade funcional permanece a mesma: o usuário continua podendo configurar múltiplos destinos pelos controles de caminhos de saída já existentes na própria janela de compressão.

Deduplicação de caminhos no fluxo de atualização
- Em `UpdateGUI.cpp`, a função `AddUniquePath()` comparava caminhos usando igualdade case-sensitive.
- Em Windows, isso podia falhar em deduplicar caminhos logicamente idênticos que diferiam apenas por maiúsculas/minúsculas.
- A comparação agora é case-insensitive (`IsEqualTo_NoCase()`), o que se alinha melhor ao comportamento esperado para caminhos no Windows e evita entradas duplicadas durante a coleta dos caminhos de itens no fluxo de atualização/compressão.
- A alteração foi mantida propositalmente mínima: ela corrige a duplicação por diferença de casing sem alterar as regras mais amplas de normalização de caminhos.

Segurança na preparação do diretório de trabalho
- `PrepareWorkingDirForArchivePath()` ignorava o valor de retorno de `MyGetFullPathName()`.
- Se a resolução para caminho absoluto falhasse, o código poderia continuar com um caminho inválido ou vazio e, a partir disso, derivar um diretório de trabalho incorreto.
- Agora a função retorna imediatamente quando `MyGetFullPathName()` falha, deixando `options.WorkingDir` vazio.
- Essa mudança é conservadora: o fluxo subsequente de atualização já possui fallback quando o diretório de trabalho está vazio, então o patch evita propagar um estado inconsistente sem alterar o modelo de fallback já existente.

Consistência de headers / limpeza não funcional
- `LangUtils.h` agora fornece um fallback para `LangString_OnlyFromLangFile()` também quando `Z7_LANG` não está definido.
- Isso não altera o comportamento funcional em builds localizados normais, mas mantém a interface do header consistente entre configurações e evita divergências em IDEs/analisadores estáticos quando `Z7_LANG` não está visível para o parser.

Impacto comportamental
- Nenhuma lógica de formato de arquivo foi alterada.
- Nenhum comportamento de codec foi alterado.
- Nenhum novo formato de persistência foi introduzido.
- As únicas mudanças observáveis em runtime são:
  - correção dos metadados exibidos pelo Windows para a instalação,
  - remoção de uma UI morta/duplicada,
  - deduplicação case-insensitive de caminhos no fluxo de atualização,
  - tratamento mais seguro de falha ao resolver caminho absoluto antes de derivar o diretório de trabalho.

Validação
- O conjunto de alterações foi validado com buscas direcionadas no código e revisão de diff para garantir que a plumbing removida da dialog/botão não deixou referências residuais.
- Também foi executado `git diff --check` nos arquivos alterados.
- Ainda não foi executado um ciclo completo de build/testes neste ambiente.
2026-03-22 01:36:40 -03:00

714 lines
18 KiB
C++

// UpdateGUI.cpp
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/StringToInt.h"
#include "../../../Windows/DLL.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/Thread.h"
#include "../Common/WorkDir.h"
#include "../Explorer/MyMessages.h"
#include "../FileManager/LangUtils.h"
#include "../FileManager/StringUtils.h"
#include "../FileManager/resourceGui.h"
#include "CompressDialog.h"
#include "UpdateGUI.h"
#include "resource2.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
static const char * const kDefaultSfxModule = "7z.sfx";
extern void AddMessageToString(UString &dest, const UString &src);
UString HResultToMessage(HRESULT errorCode);
static void AddUniquePath(UStringVector &paths, const UString &path)
{
FOR_VECTOR (i, paths)
if (path.IsEqualTo_NoCase(paths[i]))
return;
paths.Add(path);
}
static void PrepareWorkingDirForArchivePath(const UString &userArchivePath, CUpdateOptions &options)
{
NWorkDir::CInfo workDirInfo;
workDirInfo.Load();
options.WorkingDir.Empty();
if (workDirInfo.Mode != NWorkDir::NMode::kCurrent)
{
FString fullPath;
if (!MyGetFullPathName(us2fs(userArchivePath), fullPath))
return;
FString namePart;
options.WorkingDir = GetWorkDir(workDirInfo, fullPath, namePart);
CreateComplexDir(options.WorkingDir);
}
}
class CThreadUpdating: public CProgressThreadVirt
{
HRESULT ProcessVirt() Z7_override;
public:
CCodecs *codecs;
const CObjectVector<COpenType> *formatIndices;
const UString *cmdArcPath;
CUpdateCallbackGUI *UpdateCallbackGUI;
NWildcard::CCensor *WildcardCensor;
CUpdateOptions *Options;
bool needSetPath;
};
HRESULT CThreadUpdating::ProcessVirt()
{
if (!Options->SeparateItemMode)
{
CUpdateErrorInfo ei;
HRESULT res = UpdateArchive(codecs, *formatIndices, *cmdArcPath,
*WildcardCensor, *Options,
ei, UpdateCallbackGUI, UpdateCallbackGUI, needSetPath);
FinalMessage.ErrorMessage.Message = ei.Message.Ptr();
ErrorPaths = ei.FileNames;
if (res != S_OK)
return res;
return HRESULT_FROM_WIN32(ei.SystemError);
}
if (Options->SeparateItemPaths.IsEmpty() ||
Options->SeparateItemPaths.Size() != Options->SeparateItemArchivePaths.Size())
{
FinalMessage.ErrorMessage.Message = L"Invalid per-item output configuration";
return E_FAIL;
}
NUpdateArchive::CActionSet actionSet = NUpdateArchive::k_ActionSet_Add;
if (!Options->Commands.IsEmpty())
actionSet = Options->Commands.Front().ActionSet;
FOR_VECTOR (i, Options->SeparateItemPaths)
{
CUpdateOptions options = *Options;
options.SeparateItemMode = false;
options.SeparateItemPaths.Clear();
options.SeparateItemArchivePaths.Clear();
options.Commands.Clear();
CUpdateArchiveCommand command;
command.ActionSet = actionSet;
command.UserArchivePath = Options->SeparateItemArchivePaths[i];
options.Commands.Add(command);
if (!options.SetArcPath(codecs, command.UserArchivePath))
{
FinalMessage.ErrorMessage.Message = L"Update is not supported";
return E_NOTIMPL;
}
PrepareWorkingDirForArchivePath(command.UserArchivePath, options);
NWildcard::CCensor censor;
censor.AddPreItem_NoWildcard(Options->SeparateItemPaths[i]);
CUpdateErrorInfo ei;
HRESULT res = UpdateArchive(codecs, *formatIndices, command.UserArchivePath,
censor, options,
ei, UpdateCallbackGUI, UpdateCallbackGUI, false);
FinalMessage.ErrorMessage.Message = ei.Message.Ptr();
ErrorPaths = ei.FileNames;
if (res != S_OK)
return res;
if (ei.ThereIsError())
return ei.Get_HRESULT_Error();
}
return S_OK;
}
// parse command line properties
static bool ParseProp_Time_BoolPair(const CProperty &prop, const char *name, CBoolPair &bp)
{
if (!prop.Name.IsPrefixedBy_Ascii_NoCase(name))
return false;
const UString rem = prop.Name.Ptr((unsigned)strlen(name));
UString val = prop.Value;
if (!rem.IsEmpty())
{
if (!val.IsEmpty())
return true;
val = rem;
}
bool res;
if (StringToBool(val, res))
{
bp.Val = res;
bp.Def = true;
}
return true;
}
static void ParseProp(
const CProperty &prop,
NCompressDialog::CInfo &di)
{
if (ParseProp_Time_BoolPair(prop, "tm", di.MTime)) return;
if (ParseProp_Time_BoolPair(prop, "tc", di.CTime)) return;
if (ParseProp_Time_BoolPair(prop, "ta", di.ATime)) return;
}
static void ParseProperties(
const CObjectVector<CProperty> &properties,
NCompressDialog::CInfo &di)
{
FOR_VECTOR (i, properties)
{
ParseProp(properties[i], di);
}
}
static void AddProp_UString(CObjectVector<CProperty> &properties, const char *name, const UString &value)
{
CProperty prop;
prop.Name = name;
prop.Value = value;
properties.Add(prop);
}
static void AddProp_UInt32(CObjectVector<CProperty> &properties, const char *name, UInt32 value)
{
UString s;
s.Add_UInt32(value);
AddProp_UString(properties, name, s);
}
static void AddProp_bool(CObjectVector<CProperty> &properties, const char *name, bool value)
{
AddProp_UString(properties, name, UString(value ? "on": "off"));
}
static void AddProp_BoolPair(CObjectVector<CProperty> &properties,
const char *name, const CBoolPair &bp)
{
if (bp.Def)
AddProp_bool(properties, name, bp.Val);
}
static void SplitOptionsToStrings(const UString &src, UStringVector &strings)
{
SplitString(src, strings);
FOR_VECTOR (i, strings)
{
UString &s = strings[i];
if (s.Len() > 2
&& s[0] == '-'
&& MyCharLower_Ascii(s[1]) == 'm')
s.DeleteFrontal(2);
}
}
static bool IsThereMethodOverride(bool is7z, const UStringVector &strings)
{
FOR_VECTOR (i, strings)
{
const UString &s = strings[i];
if (is7z)
{
const wchar_t *end;
UInt64 n = ConvertStringToUInt64(s, &end);
if (n == 0 && *end == L'=')
return true;
}
else
{
if (s.Len() > 0)
if (s[0] == L'm' && s[1] == L'=')
return true;
}
}
return false;
}
static void ParseAndAddPropertires(CObjectVector<CProperty> &properties,
const UStringVector &strings)
{
FOR_VECTOR (i, strings)
{
const UString &s = strings[i];
CProperty property;
const int index = s.Find(L'=');
if (index < 0)
property.Name = s;
else
{
property.Name.SetFrom(s, (unsigned)index);
property.Value = s.Ptr(index + 1);
}
properties.Add(property);
}
}
static void AddProp_Size(CObjectVector<CProperty> &properties, const char *name, const UInt64 size)
{
UString s;
s.Add_UInt64(size);
s.Add_Char('b');
AddProp_UString(properties, name, s);
}
static void SetOutProperties(
CObjectVector<CProperty> &properties,
const NCompressDialog::CInfo &di,
bool is7z,
bool setMethod)
{
if (di.Level != (UInt32)(Int32)-1)
AddProp_UInt32(properties, "x", (UInt32)di.Level);
if (setMethod)
{
if (!di.Method.IsEmpty())
AddProp_UString(properties, is7z ? "0": "m", di.Method);
if (di.Dict64 != (UInt64)(Int64)-1)
{
AString name;
if (is7z)
name = "0";
name += (di.OrderMode ? "mem" : "d");
AddProp_Size(properties, name, di.Dict64);
}
/*
if (di.Dict64_Chain != (UInt64)(Int64)-1)
{
AString name;
if (is7z)
name = "0";
name += "dc";
AddProp_Size(properties, name, di.Dict64_Chain);
}
*/
if (di.Order != (UInt32)(Int32)-1)
{
AString name;
if (is7z)
name = "0";
name += (di.OrderMode ? "o" : "fb");
AddProp_UInt32(properties, name, (UInt32)di.Order);
}
}
if (!di.EncryptionMethod.IsEmpty())
AddProp_UString(properties, "em", di.EncryptionMethod);
if (di.EncryptHeadersIsAllowed)
AddProp_bool(properties, "he", di.EncryptHeaders);
if (di.SolidIsSpecified)
AddProp_Size(properties, "s", di.SolidBlockSize);
if (
// di.MultiThreadIsAllowed &&
di.NumThreads != (UInt32)(Int32)-1)
AddProp_UInt32(properties, "mt", di.NumThreads);
const NCompression::CMemUse &memUse = di.MemUsage;
if (memUse.IsDefined)
{
const char *kMemUse = "memuse";
if (memUse.IsPercent)
{
UString s;
// s += 'p'; // for debug: alternate percent method
s.Add_UInt64(memUse.Val);
s.Add_Char('%');
AddProp_UString(properties, kMemUse, s);
}
else
AddProp_Size(properties, kMemUse, memUse.Val);
}
AddProp_BoolPair(properties, "tm", di.MTime);
AddProp_BoolPair(properties, "tc", di.CTime);
AddProp_BoolPair(properties, "ta", di.ATime);
if (di.TimePrec != (UInt32)(Int32)-1)
AddProp_UInt32(properties, "tp", di.TimePrec);
}
struct C_UpdateMode_ToAction_Pair
{
NCompressDialog::NUpdateMode::EEnum UpdateMode;
const NUpdateArchive::CActionSet *ActionSet;
};
static const C_UpdateMode_ToAction_Pair g_UpdateMode_Pairs[] =
{
{ NCompressDialog::NUpdateMode::kAdd, &NUpdateArchive::k_ActionSet_Add },
{ NCompressDialog::NUpdateMode::kUpdate, &NUpdateArchive::k_ActionSet_Update },
{ NCompressDialog::NUpdateMode::kFresh, &NUpdateArchive::k_ActionSet_Fresh },
{ NCompressDialog::NUpdateMode::kSync, &NUpdateArchive::k_ActionSet_Sync }
};
static int FindActionSet(const NUpdateArchive::CActionSet &actionSet)
{
for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_UpdateMode_Pairs); i++)
if (actionSet.IsEqualTo(*g_UpdateMode_Pairs[i].ActionSet))
return (int)i;
return -1;
}
static int FindUpdateMode(NCompressDialog::NUpdateMode::EEnum mode)
{
for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_UpdateMode_Pairs); i++)
if (mode == g_UpdateMode_Pairs[i].UpdateMode)
return (int)i;
return -1;
}
static HRESULT ShowDialog(
CCodecs *codecs,
const CObjectVector<NWildcard::CCensorPath> &censor,
CUpdateOptions &options,
CUpdateCallbackGUI *callback, HWND hwndParent)
{
if (options.Commands.IsEmpty())
options.SetActionCommand_Add();
/*
FString currentDirPrefix;
#ifndef UNDER_CE
{
if (!MyGetCurrentDirectory(currentDirPrefix))
return E_FAIL;
NName::NormalizeDirPathPrefix(currentDirPrefix);
}
#endif
*/
bool oneFile = false;
NFind::CFileInfo fileInfo;
UString name;
/*
if (censor.Pairs.Size() > 0)
{
const NWildcard::CPair &pair = censor.Pairs[0];
if (pair.Head.IncludeItems.Size() > 0)
{
const NWildcard::CItem &item = pair.Head.IncludeItems[0];
if (item.ForFile)
{
name = pair.Prefix;
FOR_VECTOR (i, item.PathParts)
{
if (i > 0)
name.Add_PathSepar();
name += item.PathParts[i];
}
if (fileInfo.Find(us2fs(name)))
{
if (censor.Pairs.Size() == 1 && pair.Head.IncludeItems.Size() == 1)
oneFile = !fileInfo.IsDir();
}
}
}
}
*/
if (censor.Size() > 0)
{
const NWildcard::CCensorPath &cp = censor[0];
if (cp.Include)
{
{
if (fileInfo.Find(us2fs(cp.Path)))
{
if (censor.Size() == 1)
oneFile = !fileInfo.IsDir();
}
}
}
}
/*
// v23: we restore current dir in dialog code
#if defined(_WIN32) && !defined(UNDER_CE)
CCurrentDirRestorer curDirRestorer;
#endif
*/
CCompressDialog dialog;
NCompressDialog::CInfo &di = dialog.Info;
dialog.ArcFormats = &codecs->Formats;
{
CObjectVector<CCodecInfoUser> userCodecs;
codecs->Get_CodecsInfoUser_Vector(userCodecs);
dialog.SetMethods(userCodecs);
}
if (options.MethodMode.Type_Defined)
di.FormatIndex = options.MethodMode.Type.FormatIndex;
FOR_VECTOR (i, codecs->Formats)
{
const CArcInfoEx &ai = codecs->Formats[i];
if (!ai.UpdateEnabled)
continue;
if (!oneFile && ai.Flags_KeepName())
continue;
if ((int)i != di.FormatIndex)
{
if (ai.Flags_HashHandler())
continue;
if (ai.Name.IsEqualTo_Ascii_NoCase("swfc"))
if (!oneFile || name.Len() < 4 || !StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".swf"))
continue;
}
dialog.ArcIndices.Add(i);
}
if (dialog.ArcIndices.IsEmpty())
{
ShowErrorMessage(L"No Update Engines");
return E_FAIL;
}
di.ArcPaths.Clear();
FOR_VECTOR (i, options.Commands)
{
const CUpdateArchiveCommand &command = options.Commands[i];
UString path = command.UserArchivePath;
if (path.IsEmpty())
path = command.ArchivePath.GetFinalPath();
if (!path.IsEmpty())
di.ArcPaths.Add(path);
}
if (di.ArcPaths.IsEmpty())
di.ArcPaths.Add(options.ArchivePath.GetFinalPath());
di.ArcPath = di.ArcPaths.Front();
dialog.OriginalFileName = fs2us(fileInfo.Name);
di.ItemPaths.Clear();
FOR_VECTOR (i, censor)
{
const NWildcard::CCensorPath &cp = censor[i];
if (!cp.Include)
continue;
UString path = cp.Path;
path.Trim();
if (!path.IsEmpty())
AddUniquePath(di.ItemPaths, path);
}
di.ItemOutputItemPaths = options.SeparateItemPaths;
di.ItemArcPaths = options.SeparateItemArchivePaths;
di.SeparateItemArchives = options.SeparateItemMode;
di.PathMode = options.PathMode;
// di.CurrentDirPrefix = currentDirPrefix;
di.SFXMode = options.SfxMode;
di.OpenShareForWrite = options.OpenShareForWrite;
di.DeleteAfterCompressing = options.DeleteAfterCompressing;
di.SymLinks = options.SymLinks;
di.HardLinks = options.HardLinks;
di.AltStreams = options.AltStreams;
di.NtSecurity = options.NtSecurity;
if (options.SetArcMTime)
di.SetArcMTime.SetTrueTrue();
if (options.PreserveATime)
di.PreserveATime.SetTrueTrue();
if (callback->PasswordIsDefined)
di.Password = callback->Password;
di.KeepName = !oneFile;
NUpdateArchive::CActionSet actionSet = options.Commands.Front().ActionSet;
{
int index = FindActionSet(actionSet);
if (index < 0)
return E_NOTIMPL;
di.UpdateMode = g_UpdateMode_Pairs[(unsigned)index].UpdateMode;
}
ParseProperties(options.MethodMode.Properties, di);
if (dialog.Create(hwndParent) != IDOK)
return E_ABORT;
options.DeleteAfterCompressing = di.DeleteAfterCompressing;
options.SymLinks = di.SymLinks;
options.HardLinks = di.HardLinks;
options.AltStreams = di.AltStreams;
options.NtSecurity = di.NtSecurity;
options.SetArcMTime = di.SetArcMTime.Val;
if (di.PreserveATime.Def)
options.PreserveATime = di.PreserveATime.Val;
/*
#if defined(_WIN32) && !defined(UNDER_CE)
curDirRestorer.NeedRestore = dialog.CurrentDirWasChanged;
#endif
*/
options.VolumesSizes = di.VolumeSizes;
/*
if (di.VolumeSizeIsDefined)
{
MyMessageBox(L"Splitting to volumes is not supported");
return E_FAIL;
}
*/
{
int index = FindUpdateMode(di.UpdateMode);
if (index < 0)
return E_FAIL;
actionSet = *g_UpdateMode_Pairs[index].ActionSet;
}
options.PathMode = di.PathMode;
const CArcInfoEx &archiverInfo = codecs->Formats[di.FormatIndex];
callback->PasswordIsDefined = (!di.Password.IsEmpty());
if (callback->PasswordIsDefined)
callback->Password = di.Password;
// we clear command line options, and fill options form Dialog
options.MethodMode.Properties.Clear();
const bool is7z = archiverInfo.Is_7z();
UStringVector optionStrings;
SplitOptionsToStrings(di.Options, optionStrings);
const bool methodOverride = IsThereMethodOverride(is7z, optionStrings);
SetOutProperties(options.MethodMode.Properties, di,
is7z,
!methodOverride); // setMethod
options.OpenShareForWrite = di.OpenShareForWrite;
ParseAndAddPropertires(options.MethodMode.Properties, optionStrings);
options.SfxMode = di.SFXMode;
options.MethodMode.Type = COpenType();
options.MethodMode.Type_Defined = true;
options.MethodMode.Type.FormatIndex = di.FormatIndex;
options.Commands.Clear();
FOR_VECTOR (i, di.ArcPaths)
{
CUpdateArchiveCommand command;
command.ActionSet = actionSet;
command.UserArchivePath = di.ArcPaths[i];
options.Commands.Add(command);
}
if (options.Commands.IsEmpty())
{
CUpdateArchiveCommand command;
command.ActionSet = actionSet;
command.UserArchivePath = di.ArcPath;
options.Commands.Add(command);
}
// Paths returned by the dialog are explicit user choices. Re-parse them in
// smart mode so names like "Download" get one ".7z", while "Download.7z"
// doesn't get the archive extension appended twice.
options.ArcNameMode = k_ArcNameMode_Smart;
options.SeparateItemMode = di.SeparateItemArchives;
options.SeparateItemPaths = di.ItemOutputItemPaths;
options.SeparateItemArchivePaths = di.ItemArcPaths;
if (!options.SetArcPath(codecs, options.Commands.Front().UserArchivePath))
return E_NOTIMPL;
PrepareWorkingDirForArchivePath(options.Commands.Front().UserArchivePath, options);
return S_OK;
}
HRESULT UpdateGUI(
CCodecs *codecs,
const CObjectVector<COpenType> &formatIndices,
const UString &cmdArcPath,
NWildcard::CCensor &censor,
CUpdateOptions &options,
bool showDialog,
bool &messageWasDisplayed,
CUpdateCallbackGUI *callback,
HWND hwndParent)
{
messageWasDisplayed = false;
bool needSetPath = true;
if (showDialog)
{
RINOK(ShowDialog(codecs, censor.CensorPaths, options, callback, hwndParent))
needSetPath = false;
}
if (options.SfxMode && options.SfxModule.IsEmpty())
{
options.SfxModule = NWindows::NDLL::GetModuleDirPrefix();
options.SfxModule += kDefaultSfxModule;
}
CThreadUpdating tu;
tu.needSetPath = needSetPath;
tu.codecs = codecs;
tu.formatIndices = &formatIndices;
tu.cmdArcPath = &cmdArcPath;
tu.UpdateCallbackGUI = callback;
tu.UpdateCallbackGUI->ProgressDialog = &tu;
tu.UpdateCallbackGUI->Init();
UString title = LangString(IDS_PROGRESS_COMPRESSING);
if (!formatIndices.IsEmpty())
{
const int fin = formatIndices[0].FormatIndex;
if (fin >= 0)
if (codecs->Formats[fin].Flags_HashHandler())
title = LangString(IDS_CHECKSUM_CALCULATING);
}
/*
if (hwndParent != 0)
{
tu.ProgressDialog.MainWindow = hwndParent;
// tu.ProgressDialog.MainTitle = fileName;
tu.ProgressDialog.MainAddTitle = title + L' ';
}
*/
tu.WildcardCensor = &censor;
tu.Options = &options;
tu.IconID = IDI_ICON;
RINOK(tu.Create(title, hwndParent))
messageWasDisplayed = tu.ThreadFinishedOK && tu.MessagesDisplayed;
return tu.Result;
}