Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/CPP/7zip/UI
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/UI')
-rwxr-xr-xCPP/7zip/UI/Agent/Agent.cpp578
-rwxr-xr-xCPP/7zip/UI/Agent/Agent.h314
-rwxr-xr-xCPP/7zip/UI/Agent/AgentOut.cpp518
-rwxr-xr-xCPP/7zip/UI/Agent/AgentProxy.cpp203
-rwxr-xr-xCPP/7zip/UI/Agent/AgentProxy.h56
-rwxr-xr-xCPP/7zip/UI/Agent/ArchiveFolder.cpp72
-rwxr-xr-xCPP/7zip/UI/Agent/ArchiveFolderOpen.cpp98
-rwxr-xr-xCPP/7zip/UI/Agent/ArchiveFolderOut.cpp215
-rwxr-xr-xCPP/7zip/UI/Agent/IFolderArchive.h90
-rwxr-xr-xCPP/7zip/UI/Agent/UpdateCallbackAgent.cpp80
-rwxr-xr-xCPP/7zip/UI/Agent/UpdateCallbackAgent.h24
-rwxr-xr-xCPP/7zip/UI/Client7z/Client7z.cpp850
-rwxr-xr-xCPP/7zip/UI/Client7z/Client7z.dsp226
-rwxr-xr-xCPP/7zip/UI/Client7z/Client7z.dsw29
-rwxr-xr-xCPP/7zip/UI/Client7z/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/UI/Client7z/StdAfx.h9
-rwxr-xr-xCPP/7zip/UI/Client7z/makefile45
-rwxr-xr-xCPP/7zip/UI/Common/ArchiveCommandLine.cpp985
-rwxr-xr-xCPP/7zip/UI/Common/ArchiveCommandLine.h95
-rwxr-xr-xCPP/7zip/UI/Common/ArchiveExtractCallback.cpp448
-rwxr-xr-xCPP/7zip/UI/Common/ArchiveExtractCallback.h111
-rwxr-xr-xCPP/7zip/UI/Common/ArchiveName.cpp46
-rwxr-xr-xCPP/7zip/UI/Common/ArchiveName.h10
-rwxr-xr-xCPP/7zip/UI/Common/ArchiveOpenCallback.cpp127
-rwxr-xr-xCPP/7zip/UI/Common/ArchiveOpenCallback.h89
-rwxr-xr-xCPP/7zip/UI/Common/ArchiverInfo.cpp372
-rwxr-xr-xCPP/7zip/UI/Common/ArchiverInfo.h66
-rwxr-xr-xCPP/7zip/UI/Common/CompressCall.cpp367
-rwxr-xr-xCPP/7zip/UI/Common/CompressCall.h28
-rwxr-xr-xCPP/7zip/UI/Common/DefaultName.cpp26
-rwxr-xr-xCPP/7zip/UI/Common/DefaultName.h11
-rwxr-xr-xCPP/7zip/UI/Common/DirItem.h34
-rwxr-xr-xCPP/7zip/UI/Common/EnumDirItems.cpp281
-rwxr-xr-xCPP/7zip/UI/Common/EnumDirItems.h39
-rwxr-xr-xCPP/7zip/UI/Common/ExitCode.h27
-rwxr-xr-xCPP/7zip/UI/Common/Extract.cpp152
-rwxr-xr-xCPP/7zip/UI/Common/Extract.h59
-rwxr-xr-xCPP/7zip/UI/Common/ExtractMode.h31
-rwxr-xr-xCPP/7zip/UI/Common/ExtractingFilePath.cpp75
-rwxr-xr-xCPP/7zip/UI/Common/ExtractingFilePath.h12
-rwxr-xr-xCPP/7zip/UI/Common/HandlerLoader.h38
-rwxr-xr-xCPP/7zip/UI/Common/IFileExtractCallback.h46
-rwxr-xr-xCPP/7zip/UI/Common/OpenArchive.cpp531
-rwxr-xr-xCPP/7zip/UI/Common/OpenArchive.h134
-rwxr-xr-xCPP/7zip/UI/Common/PropIDUtils.cpp90
-rwxr-xr-xCPP/7zip/UI/Common/PropIDUtils.h11
-rwxr-xr-xCPP/7zip/UI/Common/Property.h14
-rwxr-xr-xCPP/7zip/UI/Common/SetProperties.cpp65
-rwxr-xr-xCPP/7zip/UI/Common/SetProperties.h10
-rwxr-xr-xCPP/7zip/UI/Common/SortUtils.cpp78
-rwxr-xr-xCPP/7zip/UI/Common/SortUtils.h11
-rwxr-xr-xCPP/7zip/UI/Common/StdAfx.h9
-rwxr-xr-xCPP/7zip/UI/Common/TempFiles.cpp22
-rwxr-xr-xCPP/7zip/UI/Common/TempFiles.h16
-rwxr-xr-xCPP/7zip/UI/Common/Update.cpp818
-rwxr-xr-xCPP/7zip/UI/Common/Update.h158
-rwxr-xr-xCPP/7zip/UI/Common/UpdateAction.cpp64
-rwxr-xr-xCPP/7zip/UI/Common/UpdateAction.h57
-rwxr-xr-xCPP/7zip/UI/Common/UpdateCallback.cpp258
-rwxr-xr-xCPP/7zip/UI/Common/UpdateCallback.h70
-rwxr-xr-xCPP/7zip/UI/Common/UpdatePair.cpp175
-rwxr-xr-xCPP/7zip/UI/Common/UpdatePair.h24
-rwxr-xr-xCPP/7zip/UI/Common/UpdateProduce.cpp63
-rwxr-xr-xCPP/7zip/UI/Common/UpdateProduce.h31
-rwxr-xr-xCPP/7zip/UI/Common/WorkDir.cpp64
-rwxr-xr-xCPP/7zip/UI/Common/WorkDir.h10
-rwxr-xr-xCPP/7zip/UI/Common/ZipRegistry.cpp420
-rwxr-xr-xCPP/7zip/UI/Common/ZipRegistry.h99
-rwxr-xr-xCPP/7zip/UI/Console/Console.dsp667
-rwxr-xr-xCPP/7zip/UI/Console/Console.dsw29
-rwxr-xr-xCPP/7zip/UI/Console/ConsoleClose.cpp65
-rwxr-xr-xCPP/7zip/UI/Console/ConsoleClose.h24
-rwxr-xr-xCPP/7zip/UI/Console/ExtractCallbackConsole.cpp235
-rwxr-xr-xCPP/7zip/UI/Console/ExtractCallbackConsole.h65
-rwxr-xr-xCPP/7zip/UI/Console/List.cpp532
-rwxr-xr-xCPP/7zip/UI/Console/List.h13
-rwxr-xr-xCPP/7zip/UI/Console/Main.cpp382
-rwxr-xr-xCPP/7zip/UI/Console/MainAr.cpp169
-rwxr-xr-xCPP/7zip/UI/Console/OpenCallbackConsole.cpp58
-rwxr-xr-xCPP/7zip/UI/Console/OpenCallbackConsole.h27
-rwxr-xr-xCPP/7zip/UI/Console/PercentPrinter.cpp90
-rwxr-xr-xCPP/7zip/UI/Console/PercentPrinter.h31
-rwxr-xr-xCPP/7zip/UI/Console/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/UI/Console/StdAfx.h9
-rwxr-xr-xCPP/7zip/UI/Console/UpdateCallbackConsole.cpp196
-rwxr-xr-xCPP/7zip/UI/Console/UpdateCallbackConsole.h75
-rwxr-xr-xCPP/7zip/UI/Console/UserInputUtils.cpp58
-rwxr-xr-xCPP/7zip/UI/Console/UserInputUtils.h24
-rwxr-xr-xCPP/7zip/UI/Console/afxres.h1
-rwxr-xr-xCPP/7zip/UI/Console/makefile93
-rwxr-xr-xCPP/7zip/UI/Console/resource.rc3
-rwxr-xr-xCPP/7zip/UI/Explorer/7-zip.dll.manifest1
-rwxr-xr-xCPP/7zip/UI/Explorer/ContextMenu.cpp682
-rwxr-xr-xCPP/7zip/UI/Explorer/ContextMenu.h86
-rwxr-xr-xCPP/7zip/UI/Explorer/ContextMenuFlags.h34
-rwxr-xr-xCPP/7zip/UI/Explorer/DllExports.cpp315
-rwxr-xr-xCPP/7zip/UI/Explorer/Explorer.def12
-rwxr-xr-xCPP/7zip/UI/Explorer/Explorer.dsp818
-rwxr-xr-xCPP/7zip/UI/Explorer/Explorer.dsw29
-rwxr-xr-xCPP/7zip/UI/Explorer/FoldersPage/FoldersPage.cpp157
-rwxr-xr-xCPP/7zip/UI/Explorer/FoldersPage/FoldersPage.h30
-rwxr-xr-xCPP/7zip/UI/Explorer/FoldersPage/resource.h12
-rwxr-xr-xCPP/7zip/UI/Explorer/FoldersPage/resource.rc36
-rwxr-xr-xCPP/7zip/UI/Explorer/MyMessages.cpp58
-rwxr-xr-xCPP/7zip/UI/Explorer/MyMessages.h30
-rwxr-xr-xCPP/7zip/UI/Explorer/OptionsDialog.cpp71
-rwxr-xr-xCPP/7zip/UI/Explorer/OptionsDialog.h23
-rwxr-xr-xCPP/7zip/UI/Explorer/RegistryContextMenu.cpp128
-rwxr-xr-xCPP/7zip/UI/Explorer/RegistryContextMenu.h13
-rwxr-xr-xCPP/7zip/UI/Explorer/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/UI/Explorer/StdAfx.h26
-rwxr-xr-xCPP/7zip/UI/Explorer/SystemPage/SystemPage.cpp212
-rwxr-xr-xCPP/7zip/UI/Explorer/SystemPage/SystemPage.h25
-rwxr-xr-xCPP/7zip/UI/Explorer/SystemPage/resource.h6
-rwxr-xr-xCPP/7zip/UI/Explorer/SystemPage/resource.rc24
-rwxr-xr-xCPP/7zip/UI/Explorer/makefile137
-rwxr-xr-xCPP/7zip/UI/Explorer/resource.h31
-rwxr-xr-xCPP/7zip/UI/Explorer/resource.rc38
-rwxr-xr-xCPP/7zip/UI/Far/CLSIDConst.cpp8
-rwxr-xr-xCPP/7zip/UI/Far/ExtractEngine.cpp168
-rwxr-xr-xCPP/7zip/UI/Far/ExtractEngine.h68
-rwxr-xr-xCPP/7zip/UI/Far/Far.def20
-rwxr-xr-xCPP/7zip/UI/Far/Far.dsp561
-rwxr-xr-xCPP/7zip/UI/Far/Far.dsw29
-rwxr-xr-xCPP/7zip/UI/Far/FarPlugin.h577
-rwxr-xr-xCPP/7zip/UI/Far/FarUtils.cpp416
-rwxr-xr-xCPP/7zip/UI/Far/FarUtils.h185
-rwxr-xr-xCPP/7zip/UI/Far/Main.cpp622
-rwxr-xr-xCPP/7zip/UI/Far/Messages.h152
-rwxr-xr-xCPP/7zip/UI/Far/OverwriteDialog.cpp109
-rwxr-xr-xCPP/7zip/UI/Far/OverwriteDialog.h33
-rwxr-xr-xCPP/7zip/UI/Far/Plugin.cpp693
-rwxr-xr-xCPP/7zip/UI/Far/Plugin.h99
-rwxr-xr-xCPP/7zip/UI/Far/PluginCommon.cpp50
-rwxr-xr-xCPP/7zip/UI/Far/PluginDelete.cpp169
-rwxr-xr-xCPP/7zip/UI/Far/PluginRead.cpp278
-rwxr-xr-xCPP/7zip/UI/Far/PluginWrite.cpp696
-rwxr-xr-xCPP/7zip/UI/Far/ProgressBox.cpp103
-rwxr-xr-xCPP/7zip/UI/Far/ProgressBox.h35
-rwxr-xr-xCPP/7zip/UI/Far/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/UI/Far/StdAfx.h12
-rwxr-xr-xCPP/7zip/UI/Far/UpdateCallback100.cpp54
-rwxr-xr-xCPP/7zip/UI/Far/UpdateCallback100.h45
-rwxr-xr-xCPP/7zip/UI/Far/makefile102
-rwxr-xr-xCPP/7zip/UI/Far/resource.rc3
-rwxr-xr-xCPP/7zip/UI/GUI/7zG.exe.manifest1
-rwxr-xr-xCPP/7zip/UI/GUI/CompressDialog.cpp1373
-rwxr-xr-xCPP/7zip/UI/GUI/CompressDialog.h171
-rwxr-xr-xCPP/7zip/UI/GUI/ExtractDialog.cpp371
-rwxr-xr-xCPP/7zip/UI/GUI/ExtractDialog.h77
-rwxr-xr-xCPP/7zip/UI/GUI/ExtractGUI.cpp172
-rwxr-xr-xCPP/7zip/UI/GUI/ExtractGUI.h20
-rwxr-xr-xCPP/7zip/UI/GUI/FM.icobin0 -> 4846 bytes
-rwxr-xr-xCPP/7zip/UI/GUI/GUI.cpp260
-rwxr-xr-xCPP/7zip/UI/GUI/GUI.dsp904
-rwxr-xr-xCPP/7zip/UI/GUI/GUI.dsw29
-rwxr-xr-xCPP/7zip/UI/GUI/OpenCallbackGUI.cpp65
-rwxr-xr-xCPP/7zip/UI/GUI/OpenCallbackGUI.h35
-rwxr-xr-xCPP/7zip/UI/GUI/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/UI/GUI/StdAfx.h13
-rwxr-xr-xCPP/7zip/UI/GUI/UpdateCallbackGUI.cpp167
-rwxr-xr-xCPP/7zip/UI/GUI/UpdateCallbackGUI.h63
-rwxr-xr-xCPP/7zip/UI/GUI/UpdateGUI.cpp397
-rwxr-xr-xCPP/7zip/UI/GUI/UpdateGUI.h20
-rwxr-xr-xCPP/7zip/UI/GUI/makefile135
-rwxr-xr-xCPP/7zip/UI/GUI/resource.h45
-rwxr-xr-xCPP/7zip/UI/GUI/resource.rc57
-rwxr-xr-xCPP/7zip/UI/Resource/CompressDialog/resource.h40
-rwxr-xr-xCPP/7zip/UI/Resource/CompressDialog/resource.rc117
-rwxr-xr-xCPP/7zip/UI/Resource/Extract/resource.h15
-rwxr-xr-xCPP/7zip/UI/Resource/Extract/resource.rc19
-rwxr-xr-xCPP/7zip/UI/Resource/ExtractDialog/resource.h26
-rwxr-xr-xCPP/7zip/UI/Resource/ExtractDialog/resource.rc80
-rwxr-xr-xCPP/7zip/UI/makefile10
174 files changed, 26148 insertions, 0 deletions
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp
new file mode 100755
index 00000000..f983e2f9
--- /dev/null
+++ b/CPP/7zip/UI/Agent/Agent.cpp
@@ -0,0 +1,578 @@
+// Agent.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+#include "Windows/FileFind.h"
+
+#include "../Common/DefaultName.h"
+#include "../Common/ArchiveExtractCallback.h"
+
+#include "Agent.h"
+
+#ifdef FORMAT_7Z
+#include "../../Archive/7z/7zHandler.h"
+#endif
+
+extern "C"
+{
+ #include "../../../../C/Sort.h"
+}
+
+
+using namespace NWindows;
+
+STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder)
+{
+ *agentFolder = this;
+ return S_OK;
+}
+
+void CAgentFolder::LoadFolder(CProxyFolder *folder)
+{
+ int i;
+ CProxyItem item;
+ item.Folder = folder;
+ for (i = 0; i < folder->Folders.Size(); i++)
+ {
+ item.Index = i;
+ _items.Add(item);
+ LoadFolder(&folder->Folders[i]);
+ }
+ int start = folder->Folders.Size();
+ for (i = 0; i < folder->Files.Size(); i++)
+ {
+ item.Index = start + i;
+ _items.Add(item);
+ }
+}
+
+
+STDMETHODIMP CAgentFolder::LoadItems()
+{
+ _items.Clear();
+ if (_flatMode)
+ LoadFolder(_proxyFolderItem);
+ return S_OK;
+}
+
+STDMETHODIMP CAgentFolder::GetNumberOfItems(UINT32 *numItems)
+{
+ if (_flatMode)
+ *numItems = _items.Size();
+ else
+ *numItems = _proxyFolderItem->Folders.Size() +_proxyFolderItem->Files.Size();
+ return S_OK;
+}
+
+/*
+STDMETHODIMP CAgentFolder::GetNumberOfSubFolders(UINT32 *aNumSubFolders)
+{
+ *aNumSubFolders = _proxyFolderItem->Folders.Size();
+ return S_OK;
+}
+*/
+
+UString CAgentFolder::GetName(UInt32 index) const
+{
+ UInt32 realIndex;
+ const CProxyFolder *folder;
+ if (_flatMode)
+ {
+ const CProxyItem &item = _items[index];
+ folder = item.Folder;
+ realIndex = item.Index;
+ }
+ else
+ {
+ folder = _proxyFolderItem;
+ realIndex = index;
+ }
+
+ if (realIndex < (UINT32)folder->Folders.Size())
+ return folder->Folders[realIndex].Name;
+ return folder->Files[realIndex - folder->Folders.Size()].Name;
+}
+
+UString CAgentFolder::GetPrefix(UInt32 index) const
+{
+ if (!_flatMode)
+ return UString();
+ const CProxyItem &item = _items[index];
+ const CProxyFolder *folder = item.Folder;
+ UString path;
+ while(folder != _proxyFolderItem)
+ {
+ path = folder->Name + UString(L"\\") + path;
+ folder = folder->Parent;
+ }
+ return path;
+}
+
+UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const
+{
+ return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index);
+}
+
+void CAgentFolder::GetPrefixIfAny(UInt32 index, NCOM::CPropVariant &propVariant) const
+{
+ if (!_flatMode)
+ return;
+ propVariant = GetPrefix(index);
+}
+
+
+STDMETHODIMP CAgentFolder::GetProperty(UINT32 itemIndex, PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant propVariant;
+ const CProxyFolder *folder;
+ UInt32 realIndex;
+ if (_flatMode)
+ {
+ const CProxyItem &item = _items[itemIndex];
+ folder = item.Folder;
+ realIndex = item.Index;
+ }
+ else
+ {
+ folder = _proxyFolderItem;
+ realIndex = itemIndex;
+ }
+
+ if (realIndex < (UINT32)folder->Folders.Size())
+ {
+ const CProxyFolder &item = folder->Folders[realIndex];
+ switch(propID)
+ {
+ case kpidIsFolder:
+ propVariant = true;
+ break;
+ case kpidName:
+ propVariant = item.Name;
+ break;
+ case kpidPrefix:
+ GetPrefixIfAny(itemIndex, propVariant);
+ break;
+ default:
+ if (item.IsLeaf)
+ return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
+ }
+ }
+ else
+ {
+ realIndex -= folder->Folders.Size();
+ const CProxyFile &item = folder->Files[realIndex];
+ switch(propID)
+ {
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidName:
+ propVariant = item.Name;
+ break;
+ case kpidPrefix:
+ GetPrefixIfAny(itemIndex, propVariant);
+ break;
+ default:
+ return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
+
+HRESULT CAgentFolder::BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder)
+{
+ CMyComPtr<IFolderFolder> parentFolder;
+ if (folder->Parent != _proxyFolderItem)
+ {
+ RINOK(BindToFolder(folder->Parent, &parentFolder));
+ }
+ else
+ parentFolder = this;
+ CAgentFolder *folderSpec = new CAgentFolder;
+ CMyComPtr<IFolderFolder> agentFolder = folderSpec;
+ folderSpec->Init(_proxyArchive, folder, parentFolder, _agentSpec);
+ *resultFolder = agentFolder.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CAgentFolder::BindToFolder(UINT32 index, IFolderFolder **resultFolder)
+{
+ COM_TRY_BEGIN
+
+ CProxyFolder *folder;
+ UInt32 realIndex;
+ if (_flatMode)
+ {
+ const CProxyItem &item = _items[index];
+ folder = item.Folder;
+ realIndex = item.Index;
+ }
+ else
+ {
+ folder = _proxyFolderItem;
+ realIndex = index;
+ }
+ if (realIndex >= (UINT32)folder->Folders.Size())
+ return E_INVALIDARG;
+ return BindToFolder(&folder->Folders[realIndex], resultFolder);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
+{
+ COM_TRY_BEGIN
+ int index = _proxyFolderItem->FindDirSubItemIndex(name);
+ if (index < 0)
+ return E_INVALIDARG;
+ return BindToFolder(index, resultFolder);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder)
+{
+ COM_TRY_BEGIN
+ CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
+ *resultFolder = parentFolder.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::GetName(BSTR *name)
+{
+ CMyComBSTR temp = _proxyFolderItem->Name;
+ *name = temp.Detach();
+ return S_OK;
+}
+
+
+#ifdef NEW_FOLDER_INTERFACE
+
+struct CArchiveItemPropertyTemp
+{
+ UString Name;
+ PROPID ID;
+ VARTYPE Type;
+};
+
+STDMETHODIMP CAgentFolder::GetNumberOfProperties(UINT32 *numProperties)
+{
+ COM_TRY_BEGIN
+ RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProperties));
+ if (_flatMode)
+ (*numProperties)++;
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::GetPropertyInfo(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ COM_TRY_BEGIN
+ UINT32 numProperties;
+ _agentSpec->GetArchive()->GetNumberOfProperties(&numProperties);
+ if (index < numProperties)
+ {
+ RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType));
+ if (*propID == kpidPath)
+ *propID = kpidName;
+ }
+ else
+ {
+ *name = NULL;
+ *propID = kpidPrefix;
+ *varType = VT_BSTR;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::GetTypeID(BSTR *name)
+{
+ COM_TRY_BEGIN
+ UString temp = UString(L"7-Zip.") + _agentSpec->ArchiveType;
+ CMyComBSTR bstrTemp = temp;
+ *name = bstrTemp.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::GetPath(BSTR *path)
+{
+ COM_TRY_BEGIN
+ UStringVector pathParts;
+ pathParts.Clear();
+ CMyComPtr<IFolderFolder> currentFolder = this;
+ for (;;)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ currentFolder->BindToParentFolder(&newFolder);
+ if (newFolder == NULL)
+ break;
+ CMyComBSTR aName;
+ currentFolder->GetName(&aName);
+ pathParts.Insert(0, (const wchar_t *)aName);
+ currentFolder = newFolder;
+ }
+
+ UString prefix;
+ for(int i = 0; i < pathParts.Size(); i++)
+ {
+ prefix += pathParts[i];
+ prefix += L'\\';
+ }
+
+ CMyComBSTR tempPath = prefix;
+ *path = tempPath.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::SetFlatMode(Int32 flatMode)
+{
+ _flatMode = IntToBool(flatMode);
+ return S_OK;
+}
+
+#endif
+
+void CAgentFolder::GetRealIndices(const UINT32 *indices, UINT32 numItems, CUIntVector &realIndices) const
+{
+ if (!_flatMode)
+ {
+ _proxyFolderItem->GetRealIndices(indices, numItems, realIndices);
+ return;
+ }
+ realIndices.Clear();
+ for(UINT32 i = 0; i < numItems; i++)
+ {
+ const CProxyItem &item = _items[indices[i]];
+ const CProxyFolder *folder = item.Folder;
+ UInt32 realIndex = item.Index;
+ if (realIndex < (UINT32)folder->Folders.Size())
+ continue;
+ realIndices.Add(folder->Files[realIndex - folder->Folders.Size()].Index);
+ }
+ HeapSort(&realIndices.Front(), realIndices.Size());
+}
+
+STDMETHODIMP CAgentFolder::Extract(const UINT32 *indices,
+ UINT32 numItems,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2)
+{
+ COM_TRY_BEGIN
+ CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+ UStringVector pathParts;
+ CProxyFolder *currentProxyFolder = _proxyFolderItem;
+ while (currentProxyFolder->Parent)
+ {
+ pathParts.Insert(0, currentProxyFolder->Name);
+ currentProxyFolder = currentProxyFolder->Parent;
+ }
+
+ /*
+ if (_flatMode)
+ pathMode = NExtract::NPathMode::kNoPathnames;
+ */
+
+ extractCallbackSpec->Init(_agentSpec->GetArchive(),
+ extractCallback2,
+ false,
+ path,
+ pathMode,
+ overwriteMode,
+ pathParts,
+ _agentSpec->DefaultName,
+ _agentSpec->DefaultTime,
+ _agentSpec->DefaultAttributes
+ // ,_agentSpec->_srcDirectoryPrefix
+ );
+ CUIntVector realIndices;
+ GetRealIndices(indices, numItems, realIndices);
+ return _agentSpec->GetArchive()->Extract(&realIndices.Front(),
+ realIndices.Size(), testMode, extractCallback);
+ COM_TRY_END
+}
+
+/////////////////////////////////////////
+// CAgent
+
+CAgent::CAgent():
+ _proxyArchive(NULL)
+{
+}
+
+CAgent::~CAgent()
+{
+ if (_proxyArchive != NULL)
+ delete _proxyArchive;
+}
+
+STDMETHODIMP CAgent::Open(
+ const wchar_t *filePath,
+ BSTR *archiveType,
+ // CLSID *clsIDResult,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ _archiveFilePath = filePath;
+ NFile::NFind::CFileInfoW fileInfo;
+ if (!NFile::NFind::FindFile(_archiveFilePath, fileInfo))
+ return ::GetLastError();
+ if (fileInfo.IsDirectory())
+ return E_FAIL;
+ CArchiverInfo archiverInfo0, archiverInfo1;
+ HRESULT res = OpenArchive(_archiveFilePath, _archiveLink, openArchiveCallback);
+ // _archive = _archiveLink.GetArchive();
+ DefaultName = _archiveLink.GetDefaultItemName();
+ const CArchiverInfo &ai = _archiveLink.GetArchiverInfo();
+
+ RINOK(res);
+ DefaultTime = fileInfo.LastWriteTime;
+ DefaultAttributes = fileInfo.Attributes;
+ ArchiveType = ai.Name;
+ if (archiveType != 0)
+ {
+ CMyComBSTR name = ArchiveType;
+ *archiveType = name.Detach();
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::ReOpen(
+ // const wchar_t *filePath,
+ IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ if (_proxyArchive != NULL)
+ {
+ delete _proxyArchive;
+ _proxyArchive = NULL;
+ }
+ RINOK(ReOpenArchive(_archiveLink, _archiveFilePath));
+ return ReadItems();
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::Close()
+{
+ COM_TRY_BEGIN
+ RINOK(_archiveLink.Close());
+ if (_archiveLink.GetNumLevels() > 1)
+ {
+ // return S_OK;
+ }
+ // _archive->Close();
+ return S_OK;
+ COM_TRY_END
+}
+
+/*
+STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties)
+{
+ return _archive->EnumProperties(EnumProperties);
+}
+*/
+
+HRESULT CAgent::ReadItems()
+{
+ if (_proxyArchive != NULL)
+ return S_OK;
+ _proxyArchive = new CProxyArchive();
+ return _proxyArchive->Load(GetArchive(),
+ DefaultName,
+ // _defaultTime,
+ // _defaultAttributes,
+ NULL);
+}
+
+STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder)
+{
+ COM_TRY_BEGIN
+ RINOK(ReadItems());
+ CAgentFolder *folderSpec = new CAgentFolder;
+ CMyComPtr<IFolderFolder> rootFolder = folderSpec;
+ folderSpec->Init(_proxyArchive, &_proxyArchive->RootFolder, NULL, this);
+ *resultFolder = rootFolder.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CAgent::Extract(
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2)
+{
+ COM_TRY_BEGIN
+ CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+ extractCallbackSpec->Init(GetArchive(),
+ extractCallback2,
+ false,
+ path,
+ pathMode,
+ overwriteMode,
+ UStringVector(),
+ DefaultName,
+ DefaultTime,
+ DefaultAttributes
+ // ,_srcDirectoryPrefix
+ );
+ return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetNumberOfProperties(UINT32 *numProperties)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetNumberOfProperties(numProperties);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetPropertyInfo(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ COM_TRY_BEGIN
+ RINOK(GetArchive()->GetPropertyInfo(index, name, propID, varType));
+ if (*propID == kpidPath)
+ *propID = kpidName;
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetArchiveProperty(propID, value);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetNumberOfArchiveProperties(UINT32 *numProperties)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetNumberOfArchiveProperties(numProperties);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetArchivePropertyInfo(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetArchivePropertyInfo(index,
+ name, propID, varType);
+ COM_TRY_END
+}
+
diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h
new file mode 100755
index 00000000..41f80266
--- /dev/null
+++ b/CPP/7zip/UI/Agent/Agent.h
@@ -0,0 +1,314 @@
+// Agent/Agent.h
+
+#ifndef __AGENT_AGENT_H
+#define __AGENT_AGENT_H
+
+#include "Common/MyCom.h"
+#include "Windows/PropVariant.h"
+
+#include "../Common/UpdateAction.h"
+#include "../Common/ArchiverInfo.h"
+#include "../Common/OpenArchive.h"
+
+#include "IFolderArchive.h"
+#include "AgentProxy.h"
+
+#ifndef EXCLUDE_COM
+#include "Windows/DLL.h"
+#endif
+#ifdef NEW_FOLDER_INTERFACE
+#include "../../FileManager/IFolder.h"
+#endif
+
+class CAgentFolder;
+
+// {23170F69-40C1-278A-0000-000100050001}
+DEFINE_GUID(IID_IArchiveFolderInternal,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000100050001")
+IArchiveFolderInternal: public IUnknown
+{
+public:
+ STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder) PURE;
+};
+
+struct CProxyItem
+{
+ CProxyFolder *Folder;
+ UInt32 Index;
+};
+
+class CAgent;
+
+class CAgentFolder:
+ public IFolderFolder,
+ public IArchiveFolder,
+ public IArchiveFolderInternal,
+#ifdef NEW_FOLDER_INTERFACE
+ public IEnumProperties,
+ public IFolderGetTypeID,
+ public IFolderGetPath,
+ public IFolderOperations,
+ public IFolderSetFlatMode,
+#endif
+ public CMyUnknownImp
+{
+public:
+
+ MY_QUERYINTERFACE_BEGIN
+ MY_QUERYINTERFACE_ENTRY(IFolderFolder)
+ MY_QUERYINTERFACE_ENTRY(IArchiveFolder)
+ MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal)
+ #ifdef NEW_FOLDER_INTERFACE
+ MY_QUERYINTERFACE_ENTRY(IEnumProperties)
+ MY_QUERYINTERFACE_ENTRY(IFolderGetTypeID)
+ MY_QUERYINTERFACE_ENTRY(IFolderGetPath)
+ MY_QUERYINTERFACE_ENTRY(IFolderOperations)
+ MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ // IFolderFolder
+
+ void LoadFolder(CProxyFolder *folder);
+ HRESULT BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder);
+ void GetRealIndices(const UINT32 *indices, UINT32 numItems, CUIntVector &realIndices) const;
+
+ STDMETHOD(LoadItems)();
+ STDMETHOD(GetNumberOfItems)(UINT32 *numItems);
+ STDMETHOD(GetProperty)(UINT32 itemIndex, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(BindToFolder)(UINT32 index, IFolderFolder **resultFolder);
+ STDMETHOD(BindToFolder)(const wchar_t *name, IFolderFolder **resultFolder);
+ STDMETHOD(BindToParentFolder)(IFolderFolder **resultFolder);
+ STDMETHOD(GetName)(BSTR *name);
+
+ // IArchiveFolder
+ STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback);
+
+ STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder);
+
+ #ifdef NEW_FOLDER_INTERFACE
+ STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties);
+ STDMETHOD(GetPropertyInfo)(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType);
+ STDMETHOD(GetTypeID)(BSTR *name);
+ STDMETHOD(GetPath)(BSTR *path);
+
+
+ // IFolderOperations
+ STDMETHOD(CreateFolder)(const wchar_t *name, IProgress *progress);
+ STDMETHOD(CreateFile)(const wchar_t *name, IProgress *progress);
+ STDMETHOD(Rename)(UINT32 index, const wchar_t *newName, IProgress *progress);
+ STDMETHOD(Delete)(const UINT32 *indices, UINT32 numItems, IProgress *progress);
+ STDMETHOD(CopyTo)(const UINT32 *indices, UINT32 numItems,
+ const wchar_t *path, IFolderOperationsExtractCallback *callback);
+ STDMETHOD(MoveTo)(const UINT32 *indices, UINT32 numItems,
+ const wchar_t *path, IFolderOperationsExtractCallback *callback);
+ STDMETHOD(CopyFrom)(const wchar_t *fromFolderPath,
+ const wchar_t **itemsPaths, UINT32 numItems, IProgress *progress);
+ STDMETHOD(SetProperty)(UINT32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress);
+
+ STDMETHOD(SetFlatMode)(Int32 flatMode);
+ #endif
+
+ CAgentFolder(): _proxyFolderItem(NULL), _flatMode(0) {}
+
+ void Init(CProxyArchive *proxyHandler,
+ CProxyFolder *proxyFolderItem,
+ IFolderFolder *parentFolder,
+ CAgent *agent)
+ {
+ _proxyArchive = proxyHandler;
+ _proxyFolderItem = proxyFolderItem;
+ _parentFolder = parentFolder;
+ _agent = (IInFolderArchive *)agent;
+ _agentSpec = agent;
+ }
+
+ void GetPathParts(UStringVector &pathParts);
+ HRESULT CommonUpdateOperation(
+ bool deleteOperation,
+ bool createFolderOperation,
+ bool renameOperation,
+ const wchar_t *newItemName,
+ const NUpdateArchive::CActionSet *actionSet,
+ const UINT32 *indices, UINT32 numItems,
+ IFolderArchiveUpdateCallback *updateCallback100);
+
+
+ UString GetPrefix(UInt32 index) const;
+ UString GetName(UInt32 index) const;
+ UString GetFullPathPrefixPlusPrefix(UInt32 index) const;
+ void GetPrefixIfAny(UInt32 index, NWindows::NCOM::CPropVariant &propVariant) const;
+
+public:
+ CProxyArchive *_proxyArchive;
+ CProxyFolder *_proxyFolderItem;
+ CMyComPtr<IFolderFolder> _parentFolder;
+ CMyComPtr<IInFolderArchive> _agent;
+ CAgent *_agentSpec;
+
+ CRecordVector<CProxyItem> _items;
+ bool _flatMode;
+private:
+};
+
+// {23170F69-40C1-278A-1000-000100030000}
+DEFINE_GUID(CLSID_CAgentArchiveHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00);
+
+class CAgent:
+ public IInFolderArchive,
+ #ifndef EXTRACT_ONLY
+ public IOutFolderArchive,
+ public ISetProperties,
+ #endif
+ public CMyUnknownImp
+{
+public:
+
+ MY_QUERYINTERFACE_BEGIN
+ MY_QUERYINTERFACE_ENTRY(IInFolderArchive)
+ #ifndef EXTRACT_ONLY
+ MY_QUERYINTERFACE_ENTRY(IOutFolderArchive)
+ MY_QUERYINTERFACE_ENTRY(ISetProperties)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ STDMETHOD(Open)(
+ const wchar_t *filePath,
+ // CLSID *clsIDResult,
+ BSTR *archiveType,
+ IArchiveOpenCallback *openArchiveCallback);
+
+ STDMETHOD(ReOpen)(
+ // const wchar_t *filePath,
+ IArchiveOpenCallback *openArchiveCallback);
+ /*
+ STDMETHOD(ReOpen)(IInStream *stream,
+ const wchar_t *defaultName,
+ const FILETIME *defaultTime,
+ UINT32 defaultAttributes,
+ const UINT64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ */
+ STDMETHOD(Close)();
+ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value);
+ STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties);
+ STDMETHOD(GetPropertyInfo)(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType);
+ STDMETHOD(GetNumberOfArchiveProperties)(UINT32 *numProperties);
+ STDMETHOD(GetArchivePropertyInfo)(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType);
+ STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder);
+ STDMETHOD(Extract)(
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2);
+
+ #ifndef EXTRACT_ONLY
+ STDMETHOD(SetFolder)(IFolderFolder *folder);
+ STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UINT32 numNames);
+ STDMETHOD(DeleteItems)(const wchar_t *newArchiveName, const UINT32 *indices,
+ UINT32 numItems, IFolderArchiveUpdateCallback *updateCallback);
+ STDMETHOD(DoOperation)(
+ const wchar_t *filePath,
+ const CLSID *clsID,
+ const wchar_t *newArchiveName,
+ const Byte *stateActions,
+ const wchar_t *sfxModule,
+ IFolderArchiveUpdateCallback *updateCallback);
+
+ HRESULT CommonUpdate(
+ const wchar_t *newArchiveName,
+ int numUpdateItems,
+ IArchiveUpdateCallback *updateCallback);
+
+ HRESULT CreateFolder(
+ const wchar_t *newArchiveName,
+ const wchar_t *folderName,
+ IFolderArchiveUpdateCallback *updateCallback100);
+
+ HRESULT RenameItem(
+ const wchar_t *newArchiveName,
+ const UINT32 *indices, UINT32 numItems,
+ const wchar_t *newItemName,
+ IFolderArchiveUpdateCallback *updateCallback100);
+
+ // ISetProperties
+ STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, INT32 numProperties);
+ #endif
+
+ CAgent();
+ ~CAgent();
+private:
+ HRESULT ReadItems();
+public:
+ CProxyArchive *_proxyArchive;
+
+ CArchiveLink _archiveLink;
+ // IInArchive *_archive2;
+
+ // CLSID _CLSID;
+ // CMyComPtr<IArchiveFolder> m_RootFolder;
+
+ UString DefaultName;
+
+ FILETIME DefaultTime;
+ UINT32 DefaultAttributes;
+
+ UString ArchiveType;
+
+ UStringVector _names;
+ UString _folderPrefix;
+
+ UString _archiveNamePrefix;
+ CAgentFolder *_agentFolder;
+
+ UString _archiveFilePath;
+
+ #ifndef EXTRACT_ONLY
+ CObjectVector<UString> m_PropNames;
+ CObjectVector<NWindows::NCOM::CPropVariant> m_PropValues;
+ #endif
+
+ IInArchive *GetArchive() { return _archiveLink.GetArchive(); }
+ bool CanUpdate() const { return _archiveLink.GetNumLevels() <= 1; }
+};
+
+#ifdef NEW_FOLDER_INTERFACE
+class CArchiveFolderManager:
+ public IFolderManager,
+ public IFolderManagerGetIconPath,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP2(
+ IFolderManager,
+ IFolderManagerGetIconPath
+ )
+ // IFolderManager
+ STDMETHOD(OpenFolderFile)(const wchar_t *filePath, IFolderFolder **resultFolder, IProgress *progress);
+ STDMETHOD(GetTypes)(BSTR *types);
+ STDMETHOD(GetExtension)(const wchar_t *type, BSTR *extension);
+ STDMETHOD(CreateFolderFile)(const wchar_t *type, const wchar_t *filePath, IProgress *progress);
+ STDMETHOD(GetIconPath)(const wchar_t *type, BSTR *iconPath);
+ CArchiveFolderManager(): _formatsLoaded(false) {}
+private:
+ void LoadFormats();
+ int FindFormat(const UString &type);
+ bool _formatsLoaded;
+ CObjectVector<CArchiverInfo> _formats;
+};
+#endif
+
+#endif
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp
new file mode 100755
index 00000000..25d65bb2
--- /dev/null
+++ b/CPP/7zip/UI/Agent/AgentOut.cpp
@@ -0,0 +1,518 @@
+// AgentOut.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+#include "Windows/PropVariantConversions.h"
+#include "Windows/FileDir.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../../Common/FileStreams.h"
+
+#include "../Common/UpdatePair.h"
+#include "../Common/EnumDirItems.h"
+#include "../Common/HandlerLoader.h"
+#include "../Common/UpdateCallback.h"
+#include "../Common/OpenArchive.h"
+
+#include "Agent.h"
+#include "UpdateCallbackAgent.h"
+
+using namespace NWindows;
+using namespace NCOM;
+
+static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream)
+{
+ CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+ return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
+}
+
+STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder)
+{
+ _archiveNamePrefix.Empty();
+ if (folder == NULL)
+ {
+ _agentFolder = NULL;
+ return S_OK;
+ }
+ else
+ {
+ CMyComPtr<IFolderFolder> archiveFolder = folder;
+ CMyComPtr<IArchiveFolderInternal> archiveFolderInternal;
+ RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));
+ RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder));
+ }
+
+ UStringVector pathParts;
+ pathParts.Clear();
+ CMyComPtr<IFolderFolder> folderItem = folder;
+ if (folderItem != NULL)
+ for (;;)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ folderItem->BindToParentFolder(&newFolder);
+ if (newFolder == NULL)
+ break;
+ CMyComBSTR name;
+ folderItem->GetName(&name);
+ pathParts.Insert(0, (const wchar_t *)name);
+ folderItem = newFolder;
+ }
+
+ for(int i = 0; i < pathParts.Size(); i++)
+ {
+ _archiveNamePrefix += pathParts[i];
+ _archiveNamePrefix += L'\\';
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix,
+ const wchar_t **names, UINT32 numNames)
+{
+ _folderPrefix = folderPrefix;
+ _names.Clear();
+ _names.Reserve(numNames);
+ for (UINT32 i = 0; i < numNames; i++)
+ _names.Add(names[i]);
+ return S_OK;
+}
+
+
+static HRESULT GetFileTime(CAgent *agent, UINT32 itemIndex, FILETIME &fileTime)
+{
+ CPropVariant property;
+ RINOK(agent->GetArchive()->GetProperty(itemIndex, kpidLastWriteTime, &property));
+ if (property.vt == VT_FILETIME)
+ fileTime = property.filetime;
+ else if (property.vt == VT_EMPTY)
+ fileTime = agent->DefaultTime;
+ else
+ throw 4190407;
+ return S_OK;
+}
+
+static HRESULT EnumerateArchiveItems(CAgent *agent,
+ const CProxyFolder &item,
+ const UString &prefix,
+ CObjectVector<CArchiveItem> &archiveItems)
+{
+ int i;
+ for(i = 0; i < item.Files.Size(); i++)
+ {
+ const CProxyFile &fileItem = item.Files[i];
+ CArchiveItem archiveItem;
+
+ RINOK(::GetFileTime(agent, fileItem.Index, archiveItem.LastWriteTime));
+
+ CPropVariant property;
+ agent->GetArchive()->GetProperty(fileItem.Index, kpidSize, &property);
+ archiveItem.SizeIsDefined = (property.vt != VT_EMPTY);
+ if (archiveItem.SizeIsDefined)
+ archiveItem.Size = ConvertPropVariantToUInt64(property);
+ archiveItem.IsDirectory = false;
+ archiveItem.Name = prefix + fileItem.Name;
+ archiveItem.Censored = true; // test it
+ archiveItem.IndexInServer = fileItem.Index;
+ archiveItems.Add(archiveItem);
+ }
+ for(i = 0; i < item.Folders.Size(); i++)
+ {
+ const CProxyFolder &dirItem = item.Folders[i];
+ UString fullName = prefix + dirItem.Name;
+ if(dirItem.IsLeaf)
+ {
+ CArchiveItem archiveItem;
+ RINOK(::GetFileTime(agent, dirItem.Index, archiveItem.LastWriteTime));
+ archiveItem.IsDirectory = true;
+ archiveItem.SizeIsDefined = false;
+ archiveItem.Name = fullName;
+ archiveItem.Censored = true; // test it
+ archiveItem.IndexInServer = dirItem.Index;
+ archiveItems.Add(archiveItem);
+ }
+ RINOK(EnumerateArchiveItems(agent, dirItem, fullName + UString(L'\\'), archiveItems));
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CAgent::DoOperation(
+ const wchar_t *filePath,
+ const CLSID *clsID,
+ const wchar_t *newArchiveName,
+ const Byte *stateActions,
+ const wchar_t *sfxModule,
+ IFolderArchiveUpdateCallback *updateCallback100)
+{
+ if (!CanUpdate())
+ return E_NOTIMPL;
+ NUpdateArchive::CActionSet actionSet;
+ int i;
+ for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
+ actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
+
+ CObjectVector<CDirItem> dirItems;
+
+ UString folderPrefix = _folderPrefix;
+ NFile::NName::NormalizeDirPathPrefix(folderPrefix);
+ UStringVector errorPaths;
+ CRecordVector<DWORD> errorCodes;
+ ::EnumerateDirItems(folderPrefix, _names, _archiveNamePrefix, dirItems, errorPaths, errorCodes);
+ if (errorCodes.Size() > 0)
+ {
+ return errorCodes.Front();
+ }
+
+ NWindows::NDLL::CLibrary library;
+
+ CMyComPtr<IOutArchive> outArchive;
+ if (GetArchive())
+ {
+ RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive));
+ }
+ else
+ {
+ CHandlerLoader loader;
+ RINOK(loader.CreateHandler(filePath, *clsID, (void **)&outArchive, true));
+ library.Attach(loader.Detach());
+ }
+
+ NFileTimeType::EEnum fileTimeType;
+ UINT32 value;
+ RINOK(outArchive->GetFileTimeType(&value));
+
+ switch(value)
+ {
+ case NFileTimeType::kWindows:
+ case NFileTimeType::kDOS:
+ case NFileTimeType::kUnix:
+ fileTimeType = NFileTimeType::EEnum(value);
+ break;
+ default:
+ return E_FAIL;
+ }
+
+ CObjectVector<CUpdatePair> updatePairs;
+
+ CObjectVector<CArchiveItem> archiveItems;
+ if (GetArchive())
+ {
+ RINOK(ReadItems());
+ EnumerateArchiveItems(this, _proxyArchive->RootFolder, L"", archiveItems);
+ }
+
+ GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs);
+
+ CObjectVector<CUpdatePair2> updatePairs2;
+ UpdateProduce(updatePairs, actionSet, updatePairs2);
+
+ CUpdateCallbackAgent updateCallbackAgent;
+ updateCallbackAgent.Callback = updateCallback100;
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
+
+ updateCallbackSpec->DirPrefix = folderPrefix;
+ updateCallbackSpec->DirItems = &dirItems;
+ updateCallbackSpec->ArchiveItems = &archiveItems;
+ updateCallbackSpec->UpdatePairs = &updatePairs2;
+ updateCallbackSpec->Archive = GetArchive();
+ updateCallbackSpec->Callback = &updateCallbackAgent;
+
+ COutFileStream *outStreamSpec = new COutFileStream;
+ CMyComPtr<IOutStream> outStream(outStreamSpec);
+ UString archiveName = newArchiveName;
+ {
+ UString resultPath;
+ int pos;
+ if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
+ throw 141716;
+ NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
+ }
+ if (!outStreamSpec->Create(archiveName, true))
+ {
+ // ShowLastErrorMessage();
+ return E_FAIL;
+ }
+
+ CMyComPtr<ISetProperties> setProperties;
+ if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK)
+ {
+ if (m_PropNames.Size() == 0)
+ {
+ RINOK(setProperties->SetProperties(0, 0, 0));
+ }
+ else
+ {
+ CRecordVector<const wchar_t *> names;
+ for(i = 0; i < m_PropNames.Size(); i++)
+ names.Add((const wchar_t *)m_PropNames[i]);
+
+ NWindows::NCOM::CPropVariant *propValues = new NWindows::NCOM::CPropVariant[m_PropValues.Size()];
+ try
+ {
+ for (int i = 0; i < m_PropValues.Size(); i++)
+ propValues[i] = m_PropValues[i];
+ RINOK(setProperties->SetProperties(&names.Front(), propValues, names.Size()));
+ }
+ catch(...)
+ {
+ delete []propValues;
+ throw;
+ }
+ delete []propValues;
+ }
+ }
+ m_PropNames.Clear();
+ m_PropValues.Clear();
+
+ if (sfxModule != NULL)
+ {
+ CInFileStream *sfxStreamSpec = new CInFileStream;
+ CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
+ if (!sfxStreamSpec->Open(sfxModule))
+ throw "Can't open sfx module";
+ RINOK(CopyBlock(sfxStream, outStream));
+ }
+
+ return outArchive->UpdateItems(outStream, updatePairs2.Size(),updateCallback);
+}
+
+
+HRESULT CAgent::CommonUpdate(
+ const wchar_t *newArchiveName,
+ int numUpdateItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ if (!CanUpdate())
+ return E_NOTIMPL;
+ CMyComPtr<IOutArchive> outArchive;
+ RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive));
+
+ COutFileStream *outStreamSpec = new COutFileStream;
+ CMyComPtr<IOutStream> outStream(outStreamSpec);
+
+ UString archiveName = newArchiveName;
+ {
+ UString resultPath;
+ int pos;
+ if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
+ throw 141716;
+ NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
+ }
+
+ /*
+ bool isOK = false;
+ for (int i = 0; i < (1 << 16); i++)
+ {
+ resultName = newArchiveName;
+ if (i > 0)
+ {
+ wchar_t s[32];
+ ConvertUInt64ToString(i, s);
+ resultName += s;
+ }
+ if (outStreamSpec->Open(realPath))
+ {
+ isOK = true;
+ break;
+ }
+ if (::GetLastError() != ERROR_FILE_EXISTS)
+ return ::GetLastError();
+ }
+ if (!isOK)
+ return ::GetLastError();
+ */
+ if (!outStreamSpec->Create(archiveName, true))
+ {
+ // ShowLastErrorMessage();
+ return E_FAIL;
+ }
+
+ return outArchive->UpdateItems(outStream, numUpdateItems, updateCallback);
+}
+
+
+STDMETHODIMP CAgent::DeleteItems(
+ const wchar_t *newArchiveName,
+ const UINT32 *indices, UINT32 numItems,
+ IFolderArchiveUpdateCallback *updateCallback100)
+{
+ if (!CanUpdate())
+ return E_NOTIMPL;
+ CUpdateCallbackAgent updateCallbackAgent;
+ updateCallbackAgent.Callback = updateCallback100;
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
+
+ CUIntVector realIndices;
+ _agentFolder->GetRealIndices(indices, numItems, realIndices);
+ CObjectVector<CUpdatePair2> updatePairs;
+ int curIndex = 0;
+ UInt32 numItemsInArchive;
+ RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
+ for (UInt32 i = 0; i < numItemsInArchive; i++)
+ {
+ if (curIndex < realIndices.Size())
+ if (realIndices[curIndex] == i)
+ {
+ curIndex++;
+ continue;
+ }
+ CUpdatePair2 updatePair;
+ updatePair.NewData = updatePair.NewProperties = false;
+ updatePair.ExistInArchive = true;
+ updatePair.ExistOnDisk = false;
+ updatePair.IsAnti = false; // check it. Maybe it can be undefined
+ updatePair.ArchiveItemIndex = i;
+ updatePairs.Add(updatePair);
+ }
+ updateCallbackSpec->UpdatePairs = &updatePairs;
+ updateCallbackSpec->Archive = GetArchive();
+ updateCallbackSpec->Callback = &updateCallbackAgent;
+ return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
+}
+
+HRESULT CAgent::CreateFolder(
+ const wchar_t *newArchiveName,
+ const wchar_t *folderName,
+ IFolderArchiveUpdateCallback *updateCallback100)
+{
+ if (!CanUpdate())
+ return E_NOTIMPL;
+ CUpdateCallbackAgent updateCallbackAgent;
+ updateCallbackAgent.Callback = updateCallback100;
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
+
+ CObjectVector<CUpdatePair2> updatePairs;
+ UINT32 numItemsInArchive;
+ RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
+ for (UInt32 i = 0; i < numItemsInArchive; i++)
+ {
+ CUpdatePair2 updatePair;
+ updatePair.NewData = updatePair.NewProperties = false;
+ updatePair.ExistInArchive = true;
+ updatePair.ExistOnDisk = false;
+ updatePair.IsAnti = false; // check it.
+ updatePair.ArchiveItemIndex = i;
+ updatePairs.Add(updatePair);
+ }
+ CUpdatePair2 updatePair;
+ updatePair.NewData = updatePair.NewProperties = true;
+ updatePair.ExistInArchive = false;
+ updatePair.ExistOnDisk = true;
+ updatePair.IsAnti = false;
+ updatePair.ArchiveItemIndex = -1;
+ updatePair.DirItemIndex = 0;
+
+ updatePairs.Add(updatePair);
+
+ CObjectVector<CDirItem> dirItems;
+ CDirItem dirItem;
+
+ dirItem.Attributes = FILE_ATTRIBUTE_DIRECTORY;
+ dirItem.Size = 0;
+ dirItem.Name = _agentFolder->_proxyFolderItem->GetFullPathPrefix() + folderName;
+
+ SYSTEMTIME systemTime;
+ FILETIME fileTime;
+ ::GetSystemTime(&systemTime);
+ ::SystemTimeToFileTime(&systemTime, &fileTime);
+ dirItem.LastAccessTime = dirItem.LastWriteTime =
+ dirItem.CreationTime = fileTime;
+
+ dirItems.Add(dirItem);
+
+ updateCallbackSpec->Callback = &updateCallbackAgent;
+ updateCallbackSpec->DirItems = &dirItems;
+ updateCallbackSpec->UpdatePairs = &updatePairs;
+ updateCallbackSpec->Archive = GetArchive();
+ return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
+}
+
+
+HRESULT CAgent::RenameItem(
+ const wchar_t *newArchiveName,
+ const UINT32 *indices, UINT32 numItems,
+ const wchar_t *newItemName,
+ IFolderArchiveUpdateCallback *updateCallback100)
+{
+ if (!CanUpdate())
+ return E_NOTIMPL;
+ if (numItems != 1)
+ return E_INVALIDARG;
+ CUpdateCallbackAgent updateCallbackAgent;
+ updateCallbackAgent.Callback = updateCallback100;
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
+
+ CUIntVector realIndices;
+ _agentFolder->GetRealIndices(indices, numItems, realIndices);
+
+ UString fullPrefix = _agentFolder->GetFullPathPrefixPlusPrefix(indices[0]);
+ UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]);
+ UString newItemPath = fullPrefix + newItemName;
+
+ CObjectVector<CUpdatePair2> updatePairs;
+ int curIndex = 0;
+ UINT32 numItemsInArchive;
+ RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
+ for (UInt32 i = 0; i < numItemsInArchive; i++)
+ {
+ if (curIndex < realIndices.Size())
+ if (realIndices[curIndex] == i)
+ {
+ CUpdatePair2 updatePair;
+ updatePair.NewData = false;
+ updatePair.NewProperties = true;
+ updatePair.ExistInArchive = true;
+ updatePair.ExistOnDisk = false;
+ RINOK(IsArchiveItemAnti(GetArchive(), i, updatePair.IsAnti));
+ updatePair.ArchiveItemIndex = i;
+ updatePair.NewNameIsDefined = true;
+
+ updatePair.NewName = newItemName;
+
+ UString oldFullPath;
+ RINOK(GetArchiveItemPath(GetArchive(), i, DefaultName, oldFullPath));
+
+ if (oldItemPath.CompareNoCase(oldFullPath.Left(oldItemPath.Length())) != 0)
+ return E_INVALIDARG;
+
+ updatePair.NewName = newItemPath + oldFullPath.Mid(oldItemPath.Length());
+ updatePairs.Add(updatePair);
+ curIndex++;
+ continue;
+ }
+ CUpdatePair2 updatePair;
+ updatePair.NewData = updatePair.NewProperties = false;
+ updatePair.ExistInArchive = true;
+ updatePair.ExistOnDisk = false;
+ updatePair.IsAnti = false;
+ updatePair.ArchiveItemIndex = i;
+ updatePairs.Add(updatePair);
+ }
+ updateCallbackSpec->Callback = &updateCallbackAgent;
+ updateCallbackSpec->UpdatePairs = &updatePairs;
+ updateCallbackSpec->Archive = GetArchive();
+ return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
+}
+
+STDMETHODIMP CAgent::SetProperties(const wchar_t **names,
+ const PROPVARIANT *values, INT32 numProperties)
+{
+ m_PropNames.Clear();
+ m_PropValues.Clear();
+ for (int i = 0; i < numProperties; i++)
+ {
+ m_PropNames.Add(names[i]);
+ m_PropValues.Add(values[i]);
+ }
+ return S_OK;
+}
+
+
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp
new file mode 100755
index 00000000..42063e67
--- /dev/null
+++ b/CPP/7zip/UI/Agent/AgentProxy.cpp
@@ -0,0 +1,203 @@
+// AgentProxy.cpp
+
+#include "StdAfx.h"
+
+#include "AgentProxy.h"
+
+#include "Common/MyCom.h"
+#include "Windows/PropVariant.h"
+#include "Windows/Defs.h"
+#include "../Common/OpenArchive.h"
+
+extern "C"
+{
+ #include "../../../../C/Sort.h"
+}
+
+using namespace NWindows;
+
+int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const
+{
+ int left = 0, right = Folders.Size();
+ for (;;)
+ {
+ if (left == right)
+ {
+ insertPos = left;
+ return -1;
+ }
+ int mid = (left + right) / 2;
+ int compare = name.CompareNoCase(Folders[mid].Name);
+ if (compare == 0)
+ return mid;
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+}
+
+int CProxyFolder::FindDirSubItemIndex(const UString &name) const
+{
+ int insertPos;
+ return FindDirSubItemIndex(name, insertPos);
+}
+
+void CProxyFolder::AddFileSubItem(UINT32 index, const UString &name)
+{
+ Files.Add(CProxyFile());
+ Files.Back().Name = name;
+ Files.Back().Index = index;
+}
+
+CProxyFolder* CProxyFolder::AddDirSubItem(UINT32 index, bool leaf,
+ const UString &name)
+{
+ int insertPos;
+ int folderIndex = FindDirSubItemIndex(name, insertPos);
+ if (folderIndex >= 0)
+ {
+ CProxyFolder *item = &Folders[folderIndex];
+ if(leaf)
+ {
+ item->Index = index;
+ item->IsLeaf = true;
+ }
+ return item;
+ }
+ Folders.Insert(insertPos, CProxyFolder());
+ CProxyFolder *item = &Folders[insertPos];
+ item->Name = name;
+ item->Index = index;
+ item->Parent = this;
+ item->IsLeaf = leaf;
+ return item;
+}
+
+void CProxyFolder::Clear()
+{
+ Folders.Clear();
+ Files.Clear();
+}
+
+UString CProxyFolder::GetFullPathPrefix() const
+{
+ UString result;
+ const CProxyFolder *current = this;
+ while (current->Parent != NULL)
+ {
+ result = current->Name + UString(L'\\') + result;
+ current = current->Parent;
+ }
+ return result;
+}
+
+UString CProxyFolder::GetItemName(UINT32 index) const
+{
+ if (index < (UINT32)Folders.Size())
+ return Folders[index].Name;
+ return Files[index - Folders.Size()].Name;
+}
+
+void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const
+{
+ if (IsLeaf)
+ realIndices.Add(Index);
+ int i;
+ for(i = 0; i < Folders.Size(); i++)
+ Folders[i].AddRealIndices(realIndices);
+ for(i = 0; i < Files.Size(); i++)
+ realIndices.Add(Files[i].Index);
+}
+
+void CProxyFolder::GetRealIndices(const UINT32 *indices,
+ UINT32 numItems, CUIntVector &realIndices) const
+{
+ realIndices.Clear();
+ for(UINT32 i = 0; i < numItems; i++)
+ {
+ int index = indices[i];
+ int numDirItems = Folders.Size();
+ if (index < numDirItems)
+ Folders[index].AddRealIndices(realIndices);
+ else
+ realIndices.Add(Files[index - numDirItems].Index);
+ }
+ HeapSort(&realIndices.Front(), realIndices.Size());
+}
+
+///////////////////////////////////////////////
+// CProxyArchive
+
+HRESULT CProxyArchive::Reload(IInArchive *archive, IProgress *progress)
+{
+ RootFolder.Clear();
+ return ReadObjects(archive, progress);
+}
+
+HRESULT CProxyArchive::Load(IInArchive *archive,
+ const UString &defaultName,
+ // const FILETIME &defaultTime,
+ // UINT32 defaultAttributes,
+ IProgress *progress)
+{
+ DefaultName = defaultName;
+ // DefaultTime = defaultTime;
+ // DefaultAttributes = defaultAttributes;
+ return Reload(archive, progress);
+}
+
+
+HRESULT CProxyArchive::ReadObjects(IInArchive *archiveHandler, IProgress *progress)
+{
+ UINT32 numItems;
+ RINOK(archiveHandler->GetNumberOfItems(&numItems));
+ if (progress != NULL)
+ {
+ UINT64 totalItems = numItems;
+ RINOK(progress->SetTotal(totalItems));
+ }
+ for(UINT32 i = 0; i < numItems; i++)
+ {
+ if (progress != NULL)
+ {
+ UINT64 currentItemIndex = i;
+ RINOK(progress->SetCompleted(&currentItemIndex));
+ }
+ NCOM::CPropVariant propVariantPath;
+ RINOK(archiveHandler->GetProperty(i, kpidPath, &propVariantPath));
+ CProxyFolder *currentItem = &RootFolder;
+ UString fileName;
+ if(propVariantPath.vt == VT_EMPTY)
+ fileName = DefaultName;
+ else
+ {
+ if(propVariantPath.vt != VT_BSTR)
+ return E_FAIL;
+ UString filePath = propVariantPath.bstrVal;
+
+ int len = filePath.Length();
+ for (int i = 0; i < len; i++)
+ {
+ wchar_t c = filePath[i];
+ if (c == '\\' || c == '/')
+ {
+ currentItem = currentItem->AddDirSubItem((UInt32)(Int32)-1, false, fileName);
+ fileName.Empty();
+ }
+ else
+ fileName += c;
+ }
+ }
+
+ NCOM::CPropVariant propVariantIsFolder;
+ bool isFolder;
+ RINOK(IsArchiveItemFolder(archiveHandler, i, isFolder));
+ if(isFolder)
+ currentItem->AddDirSubItem(i, true, fileName);
+ else
+ currentItem->AddFileSubItem(i, fileName);
+ }
+ return S_OK;
+}
+
diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h
new file mode 100755
index 00000000..9402cfdd
--- /dev/null
+++ b/CPP/7zip/UI/Agent/AgentProxy.h
@@ -0,0 +1,56 @@
+// AgentProxy.h
+
+#ifndef __AGENT_PROXY_H
+#define __AGENT_PROXY_H
+
+#include "Common/String.h"
+
+#include "../../Archive/IArchive.h"
+
+class CProxyFile
+{
+public:
+ UINT32 Index;
+ UString Name;
+};
+
+class CProxyFolder: public CProxyFile
+{
+public:
+ CProxyFolder *Parent;
+ CObjectVector<CProxyFolder> Folders;
+ CObjectVector<CProxyFile> Files;
+ bool IsLeaf;
+
+ CProxyFolder(): Parent(NULL) {};
+ int FindDirSubItemIndex(const UString &name, int &insertPos) const;
+ int FindDirSubItemIndex(const UString &name) const;
+ CProxyFolder* AddDirSubItem(UINT32 index,
+ bool leaf, const UString &name);
+ void AddFileSubItem(UINT32 index, const UString &name);
+ void Clear();
+
+ UString GetFullPathPrefix() const;
+ UString GetItemName(UINT32 index) const;
+ void AddRealIndices(CUIntVector &realIndices) const;
+ void GetRealIndices(const UINT32 *indices, UINT32 numItems,
+ CUIntVector &realIndices) const;
+};
+
+class CProxyArchive
+{
+ HRESULT ReadObjects(IInArchive *inArchive, IProgress *progress);
+public:
+ UString DefaultName;
+ // FILETIME DefaultTime;
+ // UINT32 DefaultAttributes;
+ CProxyFolder RootFolder;
+ HRESULT Reload(IInArchive *archive, IProgress *progress);
+ HRESULT Load(IInArchive *archive,
+ const UString &defaultName,
+ // const FILETIME &defaultTime,
+ // UINT32 defaultAttributes,
+ IProgress *progress);
+};
+
+#endif \ No newline at end of file
diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp
new file mode 100755
index 00000000..0ce553dc
--- /dev/null
+++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp
@@ -0,0 +1,72 @@
+// Zip/ArchiveFolder.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+#include "Windows/PropVariantConversions.h"
+#include "Windows/FileDir.h"
+
+#include "../../Common/FileStreams.h"
+
+#include "../Common/UpdatePair.h"
+#include "../Common/ArchiveExtractCallback.h"
+
+#include "Agent.h"
+
+using namespace NWindows;
+using namespace NCOM;
+
+STDMETHODIMP CAgentFolder::CopyTo(const UINT32 *indices, UINT32 numItems,
+ const wchar_t *path, IFolderOperationsExtractCallback *callback)
+{
+ COM_TRY_BEGIN
+ CArchiveExtractCallback *extractCallbackSpec = new
+ CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+ UStringVector pathParts;
+ CProxyFolder *currentProxyFolder = _proxyFolderItem;
+ while (currentProxyFolder->Parent)
+ {
+ pathParts.Insert(0, currentProxyFolder->Name);
+ currentProxyFolder = currentProxyFolder->Parent;
+ }
+
+ CMyComPtr<IFolderArchiveExtractCallback> extractCallback2;
+ {
+ CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback;
+ RINOK(callbackWrap.QueryInterface(
+ IID_IFolderArchiveExtractCallback, &extractCallback2));
+ }
+
+ NExtract::NPathMode::EEnum pathMode = _flatMode ?
+ NExtract::NPathMode::kNoPathnames :
+ NExtract::NPathMode::kCurrentPathnames;
+
+ extractCallbackSpec->Init(_agentSpec->GetArchive(),
+ extractCallback2,
+ false,
+ path,
+ pathMode,
+ NExtract::NOverwriteMode::kAskBefore,
+ pathParts,
+ _agentSpec->DefaultName,
+ _agentSpec->DefaultTime,
+ _agentSpec->DefaultAttributes
+ // ,_agentSpec->_srcDirectoryPrefix
+ );
+ CUIntVector realIndices;
+ GetRealIndices(indices, numItems, realIndices);
+ return _agentSpec->GetArchive()->Extract(&realIndices.Front(),
+ realIndices.Size(), BoolToInt(false), extractCallback);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::MoveTo(const UINT32 * /* indices */, UINT32 /* numItems */,
+ const wchar_t * /* path */, IFolderOperationsExtractCallback * /* callback */)
+{
+ return E_NOTIMPL;
+}
+
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
new file mode 100755
index 00000000..ce423941
--- /dev/null
+++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
@@ -0,0 +1,98 @@
+// Zip/ArchiveFolder.cpp
+
+#include "StdAfx.h"
+
+#include "Agent.h"
+
+#include "Common/StringConvert.h"
+
+#include "../Common/OpenArchive.h"
+
+static const UInt64 kMaxCheckStartPosition = 1 << 20;
+
+static inline UINT GetCurrentFileCodePage()
+ { return AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
+
+void CArchiveFolderManager::LoadFormats()
+{
+ if (!_formatsLoaded)
+ ReadArchiverInfoList(_formats);
+}
+
+int CArchiveFolderManager::FindFormat(const UString &type)
+{
+ // LoadFormats();
+ for (int i = 0; i < _formats.Size(); i++)
+ if (type.CompareNoCase(_formats[i].Name) == 0)
+ return i;
+ return -1;
+}
+
+STDMETHODIMP CArchiveFolderManager::OpenFolderFile(const wchar_t *filePath,
+ IFolderFolder **resultFolder, IProgress *progress)
+{
+ CMyComPtr<IArchiveOpenCallback> openArchiveCallback;
+ if (progress != 0)
+ {
+ CMyComPtr<IProgress> progressWrapper = progress;
+ progressWrapper.QueryInterface(IID_IArchiveOpenCallback, &openArchiveCallback);
+ }
+ CAgent *agent = new CAgent();
+ CMyComPtr<IInFolderArchive> archive = agent;
+ RINOK(agent->Open(filePath, NULL, openArchiveCallback));
+ return agent->BindToRootFolder(resultFolder);
+}
+
+/*
+HRESULT CAgent::FolderReOpen(
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ return ReOpenArchive(_archive, _archiveFilePath);
+}
+*/
+
+STDMETHODIMP CArchiveFolderManager::GetTypes(BSTR *types)
+{
+ LoadFormats();
+ UString typesStrings;
+ for(int i = 0; i < _formats.Size(); i++)
+ {
+ const CArchiverInfo &ai = _formats[i];
+ if (!ai.Associate)
+ continue;
+ if (i != 0)
+ typesStrings += L' ';
+ typesStrings += ai.Name;
+ }
+ CMyComBSTR valueTemp = typesStrings;
+ *types = valueTemp.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveFolderManager::GetExtension(const wchar_t *type, BSTR *extension)
+{
+ *extension = 0;
+ int formatIndex = FindFormat(type);
+ if (formatIndex < 0)
+ return E_INVALIDARG;
+ CMyComBSTR valueTemp = _formats[formatIndex].Extensions[0].Ext;
+ *extension = valueTemp.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *type, BSTR *iconPath)
+{
+ *iconPath = 0;
+ int formatIndex = FindFormat(type);
+ if (formatIndex < 0)
+ return E_INVALIDARG;
+ CMyComBSTR iconPathTemp = _formats[formatIndex].FilePath;
+ *iconPath = iconPathTemp.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveFolderManager::CreateFolderFile(const wchar_t * /* type */,
+ const wchar_t * /* filePath */, IProgress * /* progress */)
+{
+ return E_NOTIMPL;
+}
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
new file mode 100755
index 00000000..4d66d86d
--- /dev/null
+++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
@@ -0,0 +1,215 @@
+// FolderOut.cpp
+
+#include "StdAfx.h"
+#include "Agent.h"
+
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+#include "Windows/FileDir.h"
+
+// #include "../Common/CompressEngineCommon.h"
+#include "../Common/ZipRegistry.h"
+#include "../Common/UpdateAction.h"
+#include "../Common/WorkDir.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDirectory;
+
+static LPCWSTR kTempArcivePrefix = L"7zA";
+
+void CAgentFolder::GetPathParts(UStringVector &pathParts)
+{
+ pathParts.Clear();
+ CMyComPtr<IFolderFolder> folder = this;
+ for (;;)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ folder->BindToParentFolder(&newFolder);
+ if (newFolder == NULL)
+ break;
+ CMyComBSTR name;
+ folder->GetName(&name);
+ pathParts.Insert(0, (const wchar_t *)name);
+ folder = newFolder;
+ }
+}
+
+HRESULT CAgentFolder::CommonUpdateOperation(
+ bool deleteOperation,
+ bool createFolderOperation,
+ bool renameOperation,
+ const wchar_t *newItemName,
+ const NUpdateArchive::CActionSet *actionSet,
+ const UINT32 *indices, UINT32 numItems,
+ IFolderArchiveUpdateCallback *updateCallback100)
+{
+ NWorkDir::CInfo workDirInfo;
+ ReadWorkDirInfo(workDirInfo);
+ UString archiveFilePath = _agentSpec->_archiveFilePath;
+ UString workDir = GetWorkDir(workDirInfo, archiveFilePath );
+ CreateComplexDirectory(workDir);
+
+ CTempFileW tempFile;
+ UString tempFileName;
+ if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0)
+ return E_FAIL;
+
+ /*
+ if (SetOutProperties(anOutArchive, aCompressionInfo.Method) != S_OK)
+ return NFileOperationReturnCode::kError;
+ */
+
+ ////////////////////////////
+ // Save FolderItem;
+
+ UStringVector pathParts;
+ GetPathParts(pathParts);
+
+ HRESULT result;
+ if (deleteOperation)
+ result = _agentSpec->DeleteItems(tempFileName,
+ indices, numItems, updateCallback100);
+ else if (createFolderOperation)
+ {
+ result = _agentSpec->CreateFolder(tempFileName,
+ newItemName, updateCallback100);
+ }
+ else if (renameOperation)
+ {
+ result = _agentSpec->RenameItem(
+ tempFileName,
+ indices, numItems,
+ newItemName,
+ updateCallback100);
+ }
+ else
+ {
+ Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];
+ for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
+ actionSetByte[i] = (Byte)actionSet->StateActions[i];
+ result = _agentSpec->DoOperation(NULL, NULL,
+ tempFileName, actionSetByte, NULL, updateCallback100);
+ }
+
+ if (result != S_OK)
+ return result;
+
+ _agentSpec->Close();
+
+ // m_FolderItem = NULL;
+
+ if (!DeleteFileAlways(archiveFilePath ))
+ return GetLastError();
+
+ tempFile.DisableDeleting();
+ if (!MyMoveFile(tempFileName, archiveFilePath ))
+ return GetLastError();
+
+ RINOK(_agentSpec->ReOpen(NULL));
+
+ ////////////////////////////
+ // Restore FolderItem;
+
+ CMyComPtr<IFolderFolder> archiveFolder;
+ RINOK(_agentSpec->BindToRootFolder(&archiveFolder));
+ for (int i = 0; i < pathParts.Size(); i++)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ archiveFolder->BindToFolder(pathParts[i], &newFolder);
+ if(!newFolder)
+ break;
+ archiveFolder = newFolder;
+ }
+
+ CMyComPtr<IArchiveFolderInternal> archiveFolderInternal;
+ RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));
+ CAgentFolder *agentFolder;
+ RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder));
+ _proxyFolderItem = agentFolder->_proxyFolderItem;
+ _proxyArchive = agentFolder->_proxyArchive;
+ _parentFolder = agentFolder->_parentFolder;
+
+ return S_OK;
+}
+
+STDMETHODIMP CAgentFolder::CopyFrom(
+ const wchar_t *fromFolderPath, // test it
+ const wchar_t **itemsPaths,
+ UINT32 numItems,
+ IProgress *progress)
+{
+ COM_TRY_BEGIN
+ RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems));
+ RINOK(_agentSpec->SetFolder(this));
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
+ if (progress != 0)
+ {
+ CMyComPtr<IProgress> progressWrapper = progress;
+ RINOK(progressWrapper.QueryInterface(
+ IID_IFolderArchiveUpdateCallback, &updateCallback100));
+ }
+ return CommonUpdateOperation(false, false, false, NULL,
+ &NUpdateArchive::kAddActionSet, 0, 0, updateCallback100);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgress *progress)
+{
+ COM_TRY_BEGIN
+ RINOK(_agentSpec->SetFolder(this));
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
+ if (progress != 0)
+ {
+ CMyComPtr<IProgress> progressWrapper = progress;
+ RINOK(progressWrapper.QueryInterface(
+ IID_IFolderArchiveUpdateCallback, &updateCallback100));
+ }
+ return CommonUpdateOperation(true, false, false, NULL,
+ &NUpdateArchive::kDeleteActionSet, indices, numItems, updateCallback100);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress)
+{
+ COM_TRY_BEGIN
+ if (_proxyFolderItem->FindDirSubItemIndex(name) >= 0)
+ return ERROR_ALREADY_EXISTS;
+ RINOK(_agentSpec->SetFolder(this));
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
+ if (progress != 0)
+ {
+ CMyComPtr<IProgress> progressWrapper = progress;
+ RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
+ }
+ return CommonUpdateOperation(false, true, false, name, NULL, NULL, 0, updateCallback100);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgress *progress)
+{
+ COM_TRY_BEGIN
+ CUIntVector indices;
+ indices.Add(index);
+ RINOK(_agentSpec->SetFolder(this));
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
+ if (progress != 0)
+ {
+ CMyComPtr<IProgress> progressWrapper = progress;
+ RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
+ }
+ return CommonUpdateOperation(false, false, true, newName, NULL, &indices.Front(),
+ indices.Size(), updateCallback100);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /* progress */)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CAgentFolder::SetProperty(UINT32 /* index */, PROPID /* propID */,
+ const PROPVARIANT * /* value */, IProgress * /* progress */)
+{
+ return E_NOTIMPL;
+}
diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h
new file mode 100755
index 00000000..41d9eb22
--- /dev/null
+++ b/CPP/7zip/UI/Agent/IFolderArchive.h
@@ -0,0 +1,90 @@
+// IFolderArchive.h
+
+#ifndef __IFOLDER_ARCHIVE_H
+#define __IFOLDER_ARCHIVE_H
+
+#include "../../Archive/IArchive.h"
+// #include "../Format/Common/ArchiveInterface.h"
+#include "../../FileManager/IFolder.h"
+#include "../Common/IFileExtractCallback.h"
+#include "../Common/ExtractMode.h"
+
+// {23170F69-40C1-278A-0000-000100050000}
+DEFINE_GUID(IID_IArchiveFolder,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000100050000")
+IArchiveFolder: public IUnknown
+{
+public:
+ STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2) PURE;
+};
+
+// {23170F69-40C1-278A-0000-000100060000}
+DEFINE_GUID(IID_IInFolderArchive,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000100060000")
+IInFolderArchive: public IUnknown
+{
+public:
+ STDMETHOD(Open)(const wchar_t *filePath,
+ // CLSID *clsIDResult,
+ BSTR *archiveType,
+ IArchiveOpenCallback *openArchiveCallback) PURE;
+ STDMETHOD(ReOpen)(
+ // const wchar_t *filePath,
+ IArchiveOpenCallback *openArchiveCallback) PURE;
+ STDMETHOD(Close)() PURE;
+ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) PURE;
+ STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties) PURE;
+ STDMETHOD(GetPropertyInfo)(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType) PURE;
+ STDMETHOD(GetNumberOfArchiveProperties)(UINT32 *numProperties) PURE;
+ STDMETHOD(GetArchivePropertyInfo)(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType) PURE;
+ STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder) PURE;
+ STDMETHOD(Extract)(
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2) PURE;
+};
+
+// {23170F69-40C1-278A-0000-0001000B0000}
+DEFINE_GUID(IID_IFolderArchiveUpdateCallback,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-0001000B0000")
+IFolderArchiveUpdateCallback: public IProgress
+{
+public:
+ STDMETHOD(CompressOperation)(const wchar_t *name) PURE;
+ STDMETHOD(DeleteOperation)(const wchar_t *name) PURE;
+ STDMETHOD(OperationResult)(INT32 operationResult) PURE;
+ STDMETHOD(UpdateErrorMessage)(const wchar_t *message) PURE;
+};
+
+// {23170F69-40C1-278A-0000-0001000A0000}
+DEFINE_GUID(IID_IOutFolderArchive,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-0001000A0000")
+IOutFolderArchive: public IUnknown
+{
+ STDMETHOD(SetFolder)(IFolderFolder *folder) PURE;
+ STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UINT32 numNames) PURE;
+ STDMETHOD(DeleteItems)(const wchar_t *newArchiveName,
+ const UINT32 *indices, UINT32 numItems, IFolderArchiveUpdateCallback *updateCallback) PURE;
+ STDMETHOD(DoOperation)(
+ const wchar_t *filePath,
+ const CLSID *clsID,
+ const wchar_t *newArchiveName,
+ const Byte *stateActions,
+ const wchar_t *sfxModule,
+ IFolderArchiveUpdateCallback *updateCallback) PURE;
+};
+
+#endif
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
new file mode 100755
index 00000000..0d57307c
--- /dev/null
+++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
@@ -0,0 +1,80 @@
+// UpdateCallbackAgent.h
+
+#include "StdAfx.h"
+
+#include "Windows/Error.h"
+
+#include "UpdateCallbackAgent.h"
+
+using namespace NWindows;
+
+HRESULT CUpdateCallbackAgent::SetTotal(UINT64 size)
+{
+ if (Callback)
+ return Callback->SetTotal(size);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::SetCompleted(const UINT64 *completeValue)
+{
+ if (Callback)
+ return Callback->SetCompleted(completeValue);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::CheckBreak()
+{
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::Finilize()
+{
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemError)
+{
+ // if (systemError == ERROR_SHARING_VIOLATION)
+ {
+ if (Callback)
+ {
+ RINOK(Callback->UpdateErrorMessage(
+ UString(L"WARNING: ") +
+ NError::MyFormatMessageW(systemError) +
+ UString(L": ") +
+ UString(name)));
+ return S_FALSE;
+ }
+ }
+ // FailedFiles.Add(name);
+ return systemError;
+}
+
+HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool /* isAnti */)
+{
+ if (Callback)
+ return Callback->CompressOperation(name);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::SetOperationResult(INT32 operationResult)
+{
+ if (Callback)
+ return Callback->OperationResult(operationResult);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(INT32 *passwordIsDefined, BSTR *password)
+{
+ *passwordIsDefined = BoolToInt(false);
+ if (!_cryptoGetTextPassword)
+ {
+ if (!Callback)
+ return S_OK;
+ HRESULT result = Callback.QueryInterface(
+ IID_ICryptoGetTextPassword2, &_cryptoGetTextPassword);
+ if (result != S_OK)
+ return S_OK;
+ }
+ return _cryptoGetTextPassword->CryptoGetTextPassword2(passwordIsDefined, password);
+}
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
new file mode 100755
index 00000000..1cff501a
--- /dev/null
+++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
@@ -0,0 +1,24 @@
+// UpdateCallbackAgent.h
+
+#ifndef __UPDATECALLBACKAGENT_H
+#define __UPDATECALLBACKAGENT_H
+
+#include "../Common/UpdateCallback.h"
+#include "IFolderArchive.h"
+
+class CUpdateCallbackAgent: public IUpdateCallbackUI
+{
+ virtual HRESULT SetTotal(UINT64 size);
+ virtual HRESULT SetCompleted(const UINT64 *completeValue);
+ virtual HRESULT CheckBreak();
+ virtual HRESULT Finilize();
+ virtual HRESULT GetStream(const wchar_t *name, bool isAnti);
+ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError);
+ virtual HRESULT SetOperationResult(INT32 operationResult);
+ virtual HRESULT CryptoGetTextPassword2(INT32 *passwordIsDefined, BSTR *password);
+ CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword;
+public:
+ CMyComPtr<IFolderArchiveUpdateCallback> Callback;
+};
+
+#endif
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
new file mode 100755
index 00000000..46bdb727
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -0,0 +1,850 @@
+// Client7z.cpp
+
+#include "StdAfx.h"
+
+#include <initguid.h>
+
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+#include "../../Common/FileStreams.h"
+#include "../../Archive/IArchive.h"
+#include "../../IPassword.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/PropVariantConversions.h"
+#include "Windows/DLL.h"
+#include "Windows/FileDir.h"
+#include "Windows/FileName.h"
+#include "Windows/FileFind.h"
+
+// {23170F69-40C1-278A-1000-000110070000}
+DEFINE_GUID(CLSID_CFormat7z,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00);
+
+using namespace NWindows;
+
+static const char *kCopyrightString = "7-Zip 4.43 (7za.DLL client example) (c) 1999-2006 Igor Pavlov 2006-08-10\n";
+static const char *kHelpString =
+"Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n"
+"Examples:\n"
+" Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n"
+" Client7z.exe l archive.7z : List contents of archive.7z\n"
+" Client7z.exe x archive.7z : eXtract files from archive.7z\n";
+
+
+typedef UINT32 (WINAPI * CreateObjectFunc)(
+ const GUID *clsID,
+ const GUID *interfaceID,
+ void **outObject);
+
+#ifndef _UNICODE
+bool g_IsNT = false;
+static inline bool IsItWindowsNT()
+{
+ OSVERSIONINFO versionInfo;
+ versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+ if (!::GetVersionEx(&versionInfo))
+ return false;
+ return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+#endif
+
+void PrintString(const UString &s)
+{
+ printf("%s", (LPCSTR)GetOemString(s));
+}
+
+void PrintString(const AString &s)
+{
+ printf("%s", s);
+}
+
+void PrintNewLine()
+{
+ PrintString("\n");
+}
+
+void PrintStringLn(const AString &s)
+{
+ PrintString(s);
+ PrintNewLine();
+}
+
+static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
+{
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, propID, &prop));
+ if(prop.vt == VT_BOOL)
+ result = VARIANT_BOOLToBool(prop.boolVal);
+ else if (prop.vt == VT_EMPTY)
+ result = false;
+ else
+ return E_FAIL;
+ return S_OK;
+}
+
+static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
+{
+ return IsArchiveItemProp(archive, index, kpidIsFolder, result);
+}
+
+
+static const wchar_t *kEmptyFileAlias = L"[Content]";
+
+
+//////////////////////////////////////////////////////////////
+// Archive Open callback class
+
+
+class CArchiveOpenCallback:
+ public IArchiveOpenCallback,
+ public ICryptoGetTextPassword,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
+
+ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
+ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
+
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+
+ bool PasswordIsDefined;
+ UString Password;
+
+ CArchiveOpenCallback() : PasswordIsDefined(false) {}
+};
+
+STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 *files, const UInt64 *bytes)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 *files, const UInt64 *bytes)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password)
+{
+ if (!PasswordIsDefined)
+ {
+ // You can ask real password here from user
+ // Password = GetPassword(OutStream);
+ // PasswordIsDefined = true;
+ PrintStringLn("Password is not defined");
+ return E_ABORT;
+ }
+ CMyComBSTR tempName(Password);
+ *password = tempName.Detach();
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////
+// Archive Extracting callback class
+
+static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";
+
+static const char *kTestingString = "Testing ";
+static const char *kExtractingString = "Extracting ";
+static const char *kSkippingString = "Skipping ";
+
+static const char *kUnsupportedMethod = "Unsupported Method";
+static const char *kCRCFailed = "CRC Failed";
+static const char *kDataError = "Data Error";
+static const char *kUnknownError = "Unknown Error";
+
+class CArchiveExtractCallback:
+ public IArchiveExtractCallback,
+ public ICryptoGetTextPassword,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
+
+ // IProgress
+ STDMETHOD(SetTotal)(UInt64 size);
+ STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+ // IArchiveExtractCallback
+ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode);
+ STDMETHOD(PrepareOperation)(Int32 askExtractMode);
+ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);
+
+ // ICryptoGetTextPassword
+ STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);
+
+private:
+ CMyComPtr<IInArchive> _archiveHandler;
+ UString _directoryPath; // Output directory
+ UString _filePath; // name inside arcvhive
+ UString _diskFilePath; // full path to file on disk
+ bool _extractMode;
+ struct CProcessedFileInfo
+ {
+ FILETIME UTCLastWriteTime;
+ UInt32 Attributes;
+ bool IsDirectory;
+ bool AttributesAreDefined;
+ bool UTCLastWriteTimeIsDefined;
+ } _processedFileInfo;
+
+ COutFileStream *_outFileStreamSpec;
+ CMyComPtr<ISequentialOutStream> _outFileStream;
+
+public:
+ void Init(IInArchive *archiveHandler, const UString &directoryPath);
+
+ UInt64 NumErrors;
+ bool PasswordIsDefined;
+ UString Password;
+
+ CArchiveExtractCallback() : PasswordIsDefined(false) {}
+};
+
+void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath)
+{
+ NumErrors = 0;
+ _archiveHandler = archiveHandler;
+ _directoryPath = directoryPath;
+ NFile::NName::NormalizeDirPathPrefix(_directoryPath);
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index,
+ ISequentialOutStream **outStream, Int32 askExtractMode)
+{
+ *outStream = 0;
+ _outFileStream.Release();
+
+ {
+ // Get Name
+ NCOM::CPropVariant propVariant;
+ RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariant));
+
+ UString fullPath;
+ if(propVariant.vt == VT_EMPTY)
+ fullPath = kEmptyFileAlias;
+ else
+ {
+ if(propVariant.vt != VT_BSTR)
+ return E_FAIL;
+ fullPath = propVariant.bstrVal;
+ }
+ _filePath = fullPath;
+ }
+
+ {
+ // Get Attributes
+ NCOM::CPropVariant propVariant;
+ RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ {
+ _processedFileInfo.Attributes = 0;
+ _processedFileInfo.AttributesAreDefined = false;
+ }
+ else
+ {
+ if (propVariant.vt != VT_UI4)
+ throw "incorrect item";
+ _processedFileInfo.Attributes = propVariant.ulVal;
+ _processedFileInfo.AttributesAreDefined = true;
+ }
+ }
+
+ RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory));
+
+ {
+ // Get Modified Time
+ NCOM::CPropVariant propVariant;
+ RINOK(_archiveHandler->GetProperty(index, kpidLastWriteTime, &propVariant));
+ _processedFileInfo.UTCLastWriteTimeIsDefined = false;
+ switch(propVariant.vt)
+ {
+ case VT_EMPTY:
+ // _processedFileInfo.UTCLastWriteTime = _utcLastWriteTimeDefault;
+ break;
+ case VT_FILETIME:
+ _processedFileInfo.UTCLastWriteTime = propVariant.filetime;
+ _processedFileInfo.UTCLastWriteTimeIsDefined = true;
+ break;
+ default:
+ return E_FAIL;
+ }
+
+ }
+ {
+ // Get Size
+ NCOM::CPropVariant propVariant;
+ RINOK(_archiveHandler->GetProperty(index, kpidSize, &propVariant));
+ bool newFileSizeDefined = (propVariant.vt != VT_EMPTY);
+ UInt64 newFileSize;
+ if (newFileSizeDefined)
+ newFileSize = ConvertPropVariantToUInt64(propVariant);
+ }
+
+
+ {
+ // Create folders for file
+ int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);
+ if (slashPos >= 0)
+ NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos));
+ }
+
+ UString fullProcessedPath = _directoryPath + _filePath;
+ _diskFilePath = fullProcessedPath;
+
+ if (_processedFileInfo.IsDirectory)
+ {
+ NFile::NDirectory::CreateComplexDirectory(fullProcessedPath);
+ }
+ else
+ {
+ NFile::NFind::CFileInfoW fileInfo;
+ if(NFile::NFind::FindFile(fullProcessedPath, fileInfo))
+ {
+ if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
+ {
+ PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath);
+ return E_ABORT;
+ }
+ }
+
+ _outFileStreamSpec = new COutFileStream;
+ CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
+ if (!_outFileStreamSpec->File.Open(fullProcessedPath, CREATE_ALWAYS))
+ {
+ PrintString((UString)L"can not open output file " + fullProcessedPath);
+ return E_ABORT;
+ }
+ _outFileStream = outStreamLoc;
+ *outStream = outStreamLoc.Detach();
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
+{
+ _extractMode = false;
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract:
+ _extractMode = true;
+ };
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract:
+ PrintString(kExtractingString);
+ break;
+ case NArchive::NExtract::NAskMode::kTest:
+ PrintString(kTestingString);
+ break;
+ case NArchive::NExtract::NAskMode::kSkip:
+ PrintString(kSkippingString);
+ break;
+ };
+ PrintString(_filePath);
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
+{
+ switch(operationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kOK:
+ break;
+ default:
+ {
+ NumErrors++;
+ PrintString(" ");
+ switch(operationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
+ PrintString(kUnsupportedMethod);
+ break;
+ case NArchive::NExtract::NOperationResult::kCRCError:
+ PrintString(kCRCFailed);
+ break;
+ case NArchive::NExtract::NOperationResult::kDataError:
+ PrintString(kDataError);
+ break;
+ default:
+ PrintString(kUnknownError);
+ }
+ }
+ }
+
+ if(_outFileStream != NULL && _processedFileInfo.UTCLastWriteTimeIsDefined)
+ _outFileStreamSpec->File.SetLastWriteTime(&_processedFileInfo.UTCLastWriteTime);
+ _outFileStream.Release();
+ if (_extractMode && _processedFileInfo.AttributesAreDefined)
+ NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes);
+ PrintNewLine();
+ return S_OK;
+}
+
+
+STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
+{
+ if (!PasswordIsDefined)
+ {
+ // You can ask real password here from user
+ // Password = GetPassword(OutStream);
+ // PasswordIsDefined = true;
+ PrintStringLn("Password is not defined");
+ return E_ABORT;
+ }
+ CMyComBSTR tempName(Password);
+ *password = tempName.Detach();
+ return S_OK;
+}
+
+
+
+//////////////////////////////////////////////////////////////
+// Archive Creating callback class
+
+struct CDirItem
+{
+ UInt32 Attributes;
+ FILETIME CreationTime;
+ FILETIME LastAccessTime;
+ FILETIME LastWriteTime;
+ UInt64 Size;
+ UString Name;
+ UString FullPath;
+ bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
+};
+
+class CArchiveUpdateCallback:
+ public IArchiveUpdateCallback2,
+ public ICryptoGetTextPassword2,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)
+
+ // IProgress
+ STDMETHOD(SetTotal)(UInt64 size);
+ STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+ // IUpdateCallback2
+ STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);
+ STDMETHOD(GetUpdateItemInfo)(UInt32 index,
+ Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);
+ STDMETHOD(SetOperationResult)(Int32 operationResult);
+ STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);
+ STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);
+
+ STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
+
+public:
+ CRecordVector<UInt64> VolumesSizes;
+ UString VolName;
+ UString VolExt;
+
+ UString DirPrefix;
+ const CObjectVector<CDirItem> *DirItems;
+
+ bool PasswordIsDefined;
+ UString Password;
+ bool AskPassword;
+
+ bool m_NeedBeClosed;
+
+ UStringVector FailedFiles;
+ CRecordVector<HRESULT> FailedCodes;
+
+ CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {};
+
+ ~CArchiveUpdateCallback() { Finilize(); }
+ HRESULT Finilize();
+
+ void Init(const CObjectVector<CDirItem> *dirItems)
+ {
+ DirItems = dirItems;
+ m_NeedBeClosed = false;
+ FailedFiles.Clear();
+ FailedCodes.Clear();
+ }
+};
+
+STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)
+{
+ return S_OK;
+}
+
+
+STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **enumerator)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
+ Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
+{
+ if(newData != NULL)
+ *newData = BoolToInt(true);
+ if(newProperties != NULL)
+ *newProperties = BoolToInt(true);
+ if(indexInArchive != NULL)
+ *indexInArchive = UInt32(-1);
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant propVariant;
+
+ if (propID == kpidIsAnti)
+ {
+ propVariant = false;
+ propVariant.Detach(value);
+ return S_OK;
+ }
+
+ {
+ const CDirItem &dirItem = (*DirItems)[index];
+ switch(propID)
+ {
+ case kpidPath:
+ propVariant = dirItem.Name;
+ break;
+ case kpidIsFolder:
+ propVariant = dirItem.IsDirectory();
+ break;
+ case kpidSize:
+ propVariant = dirItem.Size;
+ break;
+ case kpidAttributes:
+ propVariant = dirItem.Attributes;
+ break;
+ case kpidLastAccessTime:
+ propVariant = dirItem.LastAccessTime;
+ break;
+ case kpidCreationTime:
+ propVariant = dirItem.CreationTime;
+ break;
+ case kpidLastWriteTime:
+ propVariant = dirItem.LastWriteTime;
+ break;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
+
+HRESULT CArchiveUpdateCallback::Finilize()
+{
+ if (m_NeedBeClosed)
+ {
+ PrintNewLine();
+ m_NeedBeClosed = false;
+ }
+ return S_OK;
+}
+
+static void GetStream2(const wchar_t *name)
+{
+ PrintString("Compressing ");
+ if (name[0] == 0)
+ name = kEmptyFileAlias;
+ PrintString(name);
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
+{
+ RINOK(Finilize());
+
+ const CDirItem &dirItem = (*DirItems)[index];
+ GetStream2(dirItem.Name);
+
+ if(dirItem.IsDirectory())
+ return S_OK;
+
+ {
+ CInFileStream *inStreamSpec = new CInFileStream;
+ CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
+ UString path = DirPrefix + dirItem.FullPath;
+ if(!inStreamSpec->Open(path))
+ {
+ DWORD sysError = ::GetLastError();
+ FailedCodes.Add(sysError);
+ FailedFiles.Add(path);
+ // if (systemError == ERROR_SHARING_VIOLATION)
+ {
+ PrintNewLine();
+ PrintStringLn("WARNING: can't open file");
+ // PrintString(NError::MyFormatMessageW(systemError));
+ return S_FALSE;
+ }
+ // return sysError;
+ }
+ *inStream = inStreamLoc.Detach();
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult)
+{
+ m_NeedBeClosed = true;
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
+{
+ if (VolumesSizes.Size() == 0)
+ return S_FALSE;
+ if (index >= (UInt32)VolumesSizes.Size())
+ index = VolumesSizes.Size() - 1;
+ *size = VolumesSizes[index];
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
+{
+ wchar_t temp[32];
+ ConvertUInt64ToString(index + 1, temp);
+ UString res = temp;
+ while (res.Length() < 2)
+ res = UString(L'0') + res;
+ UString fileName = VolName;
+ fileName += L'.';
+ fileName += res;
+ fileName += VolExt;
+ COutFileStream *streamSpec = new COutFileStream;
+ CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
+ if(!streamSpec->Create(fileName, false))
+ return ::GetLastError();
+ *volumeStream = streamLoc.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
+{
+ if (!PasswordIsDefined)
+ {
+ if (AskPassword)
+ {
+ // You can ask real password here from user
+ // Password = GetPassword(OutStream);
+ // PasswordIsDefined = true;
+ PrintStringLn("Password is not defined");
+ return E_ABORT;
+ }
+ }
+ *passwordIsDefined = BoolToInt(PasswordIsDefined);
+ CMyComBSTR tempName(Password);
+ *password = tempName.Detach();
+ return S_OK;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// Main function
+
+int
+#ifdef _MSC_VER
+__cdecl
+#endif
+main(int argc, char* argv[])
+{
+ #ifndef _UNICODE
+ g_IsNT = IsItWindowsNT();
+ #endif
+
+ PrintStringLn(kCopyrightString);
+
+ if (argc < 3)
+ {
+ PrintStringLn(kHelpString);
+ return 1;
+ }
+ NWindows::NDLL::CLibrary library;
+ if (!library.Load(TEXT("7za.dll")))
+ {
+ PrintStringLn("Can not load library");
+ return 1;
+ }
+ CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject");
+ if (createObjectFunc == 0)
+ {
+ PrintStringLn("Can not get CreateObject");
+ return 1;
+ }
+
+ AString command = argv[1];
+ UString archiveName = GetUnicodeString(argv[2], CP_OEMCP);
+ if (command.CompareNoCase("a") == 0)
+ {
+ // create archive command
+ if (argc < 4)
+ {
+ PrintStringLn(kHelpString);
+ return 1;
+ }
+ CObjectVector<CDirItem> dirItems;
+ int i;
+ for (i = 3; i < argc; i++)
+ {
+ CDirItem item;
+ UString name = GetUnicodeString(argv[i], CP_OEMCP);
+
+ NFile::NFind::CFileInfoW fileInfo;
+ if (!NFile::NFind::FindFile(name, fileInfo))
+ {
+ PrintString(UString(L"Can't find file") + name);
+ return 1;
+ }
+
+ item.Attributes = fileInfo.Attributes;
+ item.Size = fileInfo.Size;
+ item.CreationTime = fileInfo.CreationTime;
+ item.LastAccessTime = fileInfo.LastAccessTime;
+ item.LastWriteTime = fileInfo.LastWriteTime;
+ item.Name = name;
+ item.FullPath = name;
+ dirItems.Add(item);
+ }
+ COutFileStream *outFileStreamSpec = new COutFileStream;
+ CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;
+ if (!outFileStreamSpec->Create(archiveName, false))
+ {
+ PrintStringLn("can't create archive file");
+ return 1;
+ }
+
+ CMyComPtr<IOutArchive> outArchive;
+ if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK)
+ {
+ PrintStringLn("Can not get class object");
+ return 1;
+ }
+
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);
+ updateCallbackSpec->Init(&dirItems);
+ // updateCallbackSpec->PasswordIsDefined = true;
+ // updateCallbackSpec->Password = L"1";
+
+ HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback);
+ updateCallbackSpec->Finilize();
+ if (result != S_OK)
+ {
+ PrintStringLn("Update Error");
+ return 1;
+ }
+ for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++)
+ {
+ PrintNewLine();
+ PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]);
+ }
+ if (updateCallbackSpec->FailedFiles.Size() != 0)
+ return 1;
+ }
+ else
+ {
+ if (argc != 3)
+ {
+ PrintStringLn(kHelpString);
+ return 1;
+ }
+
+ bool listCommand;
+ if (command.CompareNoCase("l") == 0)
+ listCommand = true;
+ else if (command.CompareNoCase("x") == 0)
+ listCommand = false;
+ else
+ {
+ PrintStringLn("incorrect command");
+ return 1;
+ }
+
+ CMyComPtr<IInArchive> archive;
+ if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK)
+ {
+ PrintStringLn("Can not get class object");
+ return 1;
+ }
+
+ CInFileStream *fileSpec = new CInFileStream;
+ CMyComPtr<IInStream> file = fileSpec;
+
+ if (!fileSpec->Open(archiveName))
+ {
+ PrintStringLn("Can not open archive file");
+ return 1;
+ }
+
+ {
+ CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback;
+ CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);
+ openCallbackSpec->PasswordIsDefined = false;
+ // openCallbackSpec->PasswordIsDefined = true;
+ // openCallbackSpec->Password = L"1";
+
+ if (archive->Open(file, 0, openCallback) != S_OK)
+ {
+ PrintStringLn("Can not open archive");
+ return 1;
+ }
+ }
+
+ if (listCommand)
+ {
+ // List command
+ UInt32 numItems = 0;
+ archive->GetNumberOfItems(&numItems);
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ {
+ // Get uncompressed size of file
+ NWindows::NCOM::CPropVariant propVariant;
+ archive->GetProperty(i, kpidSize, &propVariant);
+ UString s = ConvertPropVariantToString(propVariant);
+ PrintString(s);
+ PrintString(" ");
+ }
+ {
+ // Get name of file
+ NWindows::NCOM::CPropVariant propVariant;
+ archive->GetProperty(i, kpidPath, &propVariant);
+ UString s = ConvertPropVariantToString(propVariant);
+ PrintString(s);
+ }
+ PrintString("\n");
+ }
+ }
+ else
+ {
+ // Extract command
+ CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
+ extractCallbackSpec->Init(archive, L""); // second parameter is output folder path
+ extractCallbackSpec->PasswordIsDefined = false;
+ // extractCallbackSpec->PasswordIsDefined = true;
+ // extractCallbackSpec->Password = L"1";
+ archive->Extract(0, (UInt32)(Int32)(-1), false, extractCallback);
+ }
+ }
+ return 0;
+}
diff --git a/CPP/7zip/UI/Client7z/Client7z.dsp b/CPP/7zip/UI/Client7z/Client7z.dsp
new file mode 100755
index 00000000..b574bdb7
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/Client7z.dsp
@@ -0,0 +1,226 @@
+# Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Client7z - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Client7z.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Client7z - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "Client7z - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Client7z - Win32 Release"
+# Name "Client7z - Win32 Debug"
+# Begin Group "Spec"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\Client7z.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/UI/Client7z/Client7z.dsw b/CPP/7zip/UI/Client7z/Client7z.dsw
new file mode 100755
index 00000000..598a6d3f
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/Client7z.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Client7z"=.\Client7z.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/UI/Client7z/StdAfx.cpp b/CPP/7zip/UI/Client7z/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/UI/Client7z/StdAfx.h b/CPP/7zip/UI/Client7z/StdAfx.h
new file mode 100755
index 00000000..b23436e9
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include <windows.h>
+#include <stdio.h>
+
+#endif
diff --git a/CPP/7zip/UI/Client7z/makefile b/CPP/7zip/UI/Client7z/makefile
new file mode 100755
index 00000000..c4ae0aaf
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/makefile
@@ -0,0 +1,45 @@
+PROG = 7z.exe
+LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib
+CFLAGS = $(CFLAGS) -I ../../../ -DCOMPRESS_MT
+
+CONSOLE_OBJS = \
+ $O\Client7z.obj \
+
+COMMON_OBJS = \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\Vector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileName.obj \
+ $O\PropVariant.obj \
+ $O\PropVariantConversions.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\FileStreams.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(CONSOLE_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+
+!include "../../../Build.mak"
+
+$(CONSOLE_OBJS): $(*B).cpp
+ $(COMPL_O1_W3)
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+ $(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+ $(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
new file mode 100755
index 00000000..6f951a27
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -0,0 +1,985 @@
+// ArchiveCommandLine.cpp
+
+#include "StdAfx.h"
+
+#include <io.h>
+#include <stdio.h>
+
+#include "Common/ListFileUtils.h"
+#include "Common/StringConvert.h"
+#include "Common/StringToInt.h"
+
+#include "Windows/FileName.h"
+#include "Windows/FileDir.h"
+#ifdef _WIN32
+#include "Windows/FileMapping.h"
+#include "Windows/Synchronization.h"
+#endif
+
+#include "ArchiveCommandLine.h"
+#include "UpdateAction.h"
+#include "Update.h"
+#include "ArchiverInfo.h"
+#include "SortUtils.h"
+#include "EnumDirItems.h"
+
+using namespace NCommandLineParser;
+using namespace NWindows;
+using namespace NFile;
+
+static const int kNumSwitches = 28;
+
+namespace NKey {
+enum Enum
+{
+ kHelp1 = 0,
+ kHelp2,
+ kHelp3,
+ kDisableHeaders,
+ kDisablePercents,
+ kArchiveType,
+ kYes,
+ kPassword,
+ kProperty,
+ kOutputDir,
+ kWorkingDir,
+ kInclude,
+ kExclude,
+ kArInclude,
+ kArExclude,
+ kNoArName,
+ kUpdate,
+ kVolume,
+ kRecursed,
+ kSfx,
+ kStdIn,
+ kStdOut,
+ kOverwrite,
+ kEmail,
+ kShowDialog,
+ kLargePages,
+ kCharSet,
+ kTechMode
+};
+
+}
+
+
+static const wchar_t kRecursedIDChar = 'R';
+static const wchar_t *kRecursedPostCharSet = L"0-";
+
+static const wchar_t *kDefaultArchiveType = L"7z";
+static const wchar_t *kSFXExtension =
+ #ifdef _WIN32
+ L"exe";
+ #else
+ L"";
+ #endif
+
+namespace NRecursedPostCharIndex {
+ enum EEnum
+ {
+ kWildCardRecursionOnly = 0,
+ kNoRecursion = 1
+ };
+}
+
+static const char kImmediateNameID = '!';
+static const char kMapNameID = '#';
+static const char kFileListID = '@';
+
+static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be
+static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be
+
+static const wchar_t *kOverwritePostCharSet = L"asut";
+
+NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =
+{
+ NExtract::NOverwriteMode::kWithoutPrompt,
+ NExtract::NOverwriteMode::kSkipExisting,
+ NExtract::NOverwriteMode::kAutoRename,
+ NExtract::NOverwriteMode::kAutoRenameExisting
+};
+
+static const CSwitchForm kSwitchForms[kNumSwitches] =
+ {
+ { L"?", NSwitchType::kSimple, false },
+ { L"H", NSwitchType::kSimple, false },
+ { L"-HELP", NSwitchType::kSimple, false },
+ { L"BA", NSwitchType::kSimple, false },
+ { L"BD", NSwitchType::kSimple, false },
+ { L"T", NSwitchType::kUnLimitedPostString, false, 1 },
+ { L"Y", NSwitchType::kSimple, false },
+ { L"P", NSwitchType::kUnLimitedPostString, false, 0 },
+ { L"M", NSwitchType::kUnLimitedPostString, true, 1 },
+ { L"O", NSwitchType::kUnLimitedPostString, false, 1 },
+ { L"W", NSwitchType::kUnLimitedPostString, false, 0 },
+ { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
+ { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
+ { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
+ { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
+ { L"AN", NSwitchType::kSimple, false },
+ { L"U", NSwitchType::kUnLimitedPostString, true, 1},
+ { L"V", NSwitchType::kUnLimitedPostString, true, 1},
+ { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet },
+ { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 },
+ { L"SI", NSwitchType::kUnLimitedPostString, false, 0 },
+ { L"SO", NSwitchType::kSimple, false, 0 },
+ { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet},
+ { L"SEML", NSwitchType::kUnLimitedPostString, false, 0},
+ { L"AD", NSwitchType::kSimple, false },
+ { L"SLP", NSwitchType::kUnLimitedPostString, false, 0},
+ { L"SCS", NSwitchType::kUnLimitedPostString, false, 0},
+ { L"SLT", NSwitchType::kSimple, false }
+ };
+
+static const int kNumCommandForms = 7;
+
+static const CCommandForm g_CommandForms[kNumCommandForms] =
+{
+ { L"A", false },
+ { L"U", false },
+ { L"D", false },
+ { L"T", false },
+ { L"E", false },
+ { L"X", false },
+ { L"L", false }
+};
+
+static const int kMaxCmdLineSize = 1000;
+static const wchar_t *kUniversalWildcard = L"*";
+static const int kMinNonSwitchWords = 1;
+static const int kCommandIndex = 0;
+
+// ---------------------------
+// exception messages
+
+static const char *kUserErrorMessage = "Incorrect command line";
+static const char *kIncorrectListFile = "Incorrect wildcard in listfile";
+static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile";
+static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line";
+static const char *kTerminalOutError = "I won't write compressed data to a terminal";
+static const char *kSameTerminalError = "I won't write data and program's messages to same terminal";
+
+static void ThrowException(const char *errorMessage)
+{
+ throw CArchiveCommandLineException(errorMessage);
+};
+
+static void ThrowUserErrorException()
+{
+ ThrowException(kUserErrorMessage);
+};
+
+// ---------------------------
+
+bool CArchiveCommand::IsFromExtractGroup() const
+{
+ switch(CommandType)
+ {
+ case NCommandType::kTest:
+ case NCommandType::kExtract:
+ case NCommandType::kFullExtract:
+ return true;
+ default:
+ return false;
+ }
+}
+
+NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const
+{
+ switch(CommandType)
+ {
+ case NCommandType::kTest:
+ case NCommandType::kFullExtract:
+ return NExtract::NPathMode::kFullPathnames;
+ default:
+ return NExtract::NPathMode::kNoPathnames;
+ }
+}
+
+bool CArchiveCommand::IsFromUpdateGroup() const
+{
+ return (CommandType == NCommandType::kAdd ||
+ CommandType == NCommandType::kUpdate ||
+ CommandType == NCommandType::kDelete);
+}
+
+static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)
+{
+ switch (index)
+ {
+ case NRecursedPostCharIndex::kWildCardRecursionOnly:
+ return NRecursedType::kWildCardOnlyRecursed;
+ case NRecursedPostCharIndex::kNoRecursion:
+ return NRecursedType::kNonRecursed;
+ default:
+ return NRecursedType::kRecursed;
+ }
+}
+
+static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)
+{
+ UString commandStringUpper = commandString;
+ commandStringUpper.MakeUpper();
+ UString postString;
+ int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper,
+ postString) ;
+ if (commandIndex < 0)
+ return false;
+ command.CommandType = (NCommandType::EEnum)commandIndex;
+ return true;
+}
+
+// ------------------------------------------------------------------
+// filenames functions
+
+static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,
+ const UString &name, bool include, NRecursedType::EEnum type)
+{
+ bool isWildCard = DoesNameContainWildCard(name);
+ bool recursed = false;
+
+ switch (type)
+ {
+ case NRecursedType::kWildCardOnlyRecursed:
+ recursed = isWildCard;
+ break;
+ case NRecursedType::kRecursed:
+ recursed = true;
+ break;
+ case NRecursedType::kNonRecursed:
+ recursed = false;
+ break;
+ }
+ wildcardCensor.AddItem(include, name, recursed);
+ return true;
+}
+
+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
+
+static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor,
+ LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage)
+{
+ UStringVector names;
+ if (!ReadNamesFromListFile(GetSystemString(fileName, GetCurrentCodePage()), names, codePage))
+ throw kIncorrectListFile;
+ for (int i = 0; i < names.Size(); i++)
+ if (!AddNameToCensor(wildcardCensor, names[i], include, type))
+ throw kIncorrectWildCardInListFile;
+}
+
+static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor,
+ const UString &name, bool include, NRecursedType::EEnum recursedType)
+{
+ if (!AddNameToCensor(wildcardCensor, name, include, recursedType))
+ throw kIncorrectWildCardInCommandLine;
+}
+
+static void AddToCensorFromNonSwitchesStrings(
+ int startIndex,
+ NWildcard::CCensor &wildcardCensor,
+ const UStringVector &nonSwitchStrings, NRecursedType::EEnum type,
+ bool thereAreSwitchIncludes, UINT codePage)
+{
+ if(nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes))
+ AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type);
+ for(int i = startIndex; i < nonSwitchStrings.Size(); i++)
+ {
+ const UString &s = nonSwitchStrings[i];
+ if (s[0] == kFileListID)
+ AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage);
+ else
+ AddCommandLineWildCardToCensr(wildcardCensor, s, true, type);
+ }
+}
+
+#ifdef _WIN32
+static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor,
+ const UString &switchParam, bool include,
+ NRecursedType::EEnum commonRecursedType)
+{
+ int splitPos = switchParam.Find(L':');
+ if (splitPos < 0)
+ ThrowUserErrorException();
+ UString mappingName = switchParam.Left(splitPos);
+
+ UString switchParam2 = switchParam.Mid(splitPos + 1);
+ splitPos = switchParam2.Find(L':');
+ if (splitPos < 0)
+ ThrowUserErrorException();
+
+ UString mappingSize = switchParam2.Left(splitPos);
+ UString eventName = switchParam2.Mid(splitPos + 1);
+
+ UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL);
+ UInt32 dataSize = (UInt32)dataSize64;
+ {
+ CFileMapping fileMapping;
+ if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName)))
+ ThrowException("Can not open mapping");
+ LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize);
+ if (data == NULL)
+ ThrowException("MapViewOfFile error");
+ try
+ {
+ const wchar_t *curData = (const wchar_t *)data;
+ if (*curData != 0)
+ ThrowException("Incorrect mapping data");
+ UInt32 numChars = dataSize / sizeof(wchar_t);
+ UString name;
+ for (UInt32 i = 1; i < numChars; i++)
+ {
+ wchar_t c = curData[i];
+ if (c == L'\0')
+ {
+ AddCommandLineWildCardToCensr(wildcardCensor,
+ name, include, commonRecursedType);
+ name.Empty();
+ }
+ else
+ name += c;
+ }
+ if (!name.IsEmpty())
+ ThrowException("data error");
+ }
+ catch(...)
+ {
+ UnmapViewOfFile(data);
+ throw;
+ }
+ UnmapViewOfFile(data);
+ }
+
+ {
+ NSynchronization::CEvent event;
+ event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName));
+ event.Set();
+ }
+}
+#endif
+
+static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor,
+ const UStringVector &strings, bool include,
+ NRecursedType::EEnum commonRecursedType, UINT codePage)
+{
+ for(int i = 0; i < strings.Size(); i++)
+ {
+ const UString &name = strings[i];
+ NRecursedType::EEnum recursedType;
+ int pos = 0;
+ if (name.Length() < kSomeCludePostStringMinSize)
+ ThrowUserErrorException();
+ if (::MyCharUpper(name[pos]) == kRecursedIDChar)
+ {
+ pos++;
+ int index = UString(kRecursedPostCharSet).Find(name[pos]);
+ recursedType = GetRecursedTypeFromIndex(index);
+ if (index >= 0)
+ pos++;
+ }
+ else
+ recursedType = commonRecursedType;
+ if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize)
+ ThrowUserErrorException();
+ UString tail = name.Mid(pos + 1);
+ if (name[pos] == kImmediateNameID)
+ AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType);
+ else if (name[pos] == kFileListID)
+ AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage);
+ #ifdef _WIN32
+ else if (name[pos] == kMapNameID)
+ ParseMapWithPaths(wildcardCensor, tail, include, recursedType);
+ #endif
+ else
+ ThrowUserErrorException();
+ }
+}
+
+#ifdef _WIN32
+
+// This code converts all short file names to long file names.
+
+static void ConvertToLongName(const UString &prefix, UString &name)
+{
+ if (name.IsEmpty() || DoesNameContainWildCard(name))
+ return;
+ NFind::CFileInfoW fileInfo;
+ if (NFind::FindFile(prefix + name, fileInfo))
+ name = fileInfo.Name;
+}
+
+static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)
+{
+ for (int i = 0; i < items.Size(); i++)
+ {
+ NWildcard::CItem &item = items[i];
+ if (item.Recursive || item.PathParts.Size() != 1)
+ continue;
+ ConvertToLongName(prefix, item.PathParts.Front());
+ }
+}
+
+static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node)
+{
+ ConvertToLongNames(prefix, node.IncludeItems);
+ ConvertToLongNames(prefix, node.ExcludeItems);
+ int i;
+ for (i = 0; i < node.SubNodes.Size(); i++)
+ ConvertToLongName(prefix, node.SubNodes[i].Name);
+ // mix folders with same name
+ for (i = 0; i < node.SubNodes.Size(); i++)
+ {
+ NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];
+ for (int j = i + 1; j < node.SubNodes.Size();)
+ {
+ const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];
+ if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0)
+ {
+ nextNode1.IncludeItems += nextNode2.IncludeItems;
+ nextNode1.ExcludeItems += nextNode2.ExcludeItems;
+ node.SubNodes.Delete(j);
+ }
+ else
+ j++;
+ }
+ }
+ for (i = 0; i < node.SubNodes.Size(); i++)
+ {
+ NWildcard::CCensorNode &nextNode = node.SubNodes[i];
+ ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode);
+ }
+}
+
+static void ConvertToLongNames(NWildcard::CCensor &censor)
+{
+ for (int i = 0; i < censor.Pairs.Size(); i++)
+ {
+ NWildcard::CPair &pair = censor.Pairs[i];
+ ConvertToLongNames(pair.Prefix, pair.Head);
+ }
+}
+
+#endif
+
+static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)
+{
+ switch(i)
+ {
+ case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore;
+ case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy;
+ case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress;
+ case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti;
+ }
+ throw 98111603;
+}
+
+const UString kUpdatePairStateIDSet = L"PQRXYZW";
+const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};
+
+const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti
+
+const wchar_t *kUpdateIgnoreItselfPostStringID = L"-";
+const wchar_t kUpdateNewArchivePostCharID = '!';
+
+
+static bool ParseUpdateCommandString2(const UString &command,
+ NUpdateArchive::CActionSet &actionSet, UString &postString)
+{
+ for(int i = 0; i < command.Length();)
+ {
+ wchar_t c = MyCharUpper(command[i]);
+ int statePos = kUpdatePairStateIDSet.Find(c);
+ if (statePos < 0)
+ {
+ postString = command.Mid(i);
+ return true;
+ }
+ i++;
+ if (i >= command.Length())
+ return false;
+ int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i]));
+ if (actionPos < 0)
+ return false;
+ actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos);
+ if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)
+ return false;
+ i++;
+ }
+ postString.Empty();
+ return true;
+}
+
+static void ParseUpdateCommandString(CUpdateOptions &options,
+ const UStringVector &updatePostStrings,
+ const NUpdateArchive::CActionSet &defaultActionSet)
+{
+ for(int i = 0; i < updatePostStrings.Size(); i++)
+ {
+ const UString &updateString = updatePostStrings[i];
+ if(updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0)
+ {
+ if(options.UpdateArchiveItself)
+ {
+ options.UpdateArchiveItself = false;
+ options.Commands.Delete(0);
+ }
+ }
+ else
+ {
+ NUpdateArchive::CActionSet actionSet = defaultActionSet;
+
+ UString postString;
+ if (!ParseUpdateCommandString2(updateString, actionSet, postString))
+ ThrowUserErrorException();
+ if(postString.IsEmpty())
+ {
+ if(options.UpdateArchiveItself)
+ options.Commands[0].ActionSet = actionSet;
+ }
+ else
+ {
+ if(MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID)
+ ThrowUserErrorException();
+ CUpdateArchiveCommand uc;
+ UString archivePath = postString.Mid(1);
+ if (archivePath.IsEmpty())
+ ThrowUserErrorException();
+ uc.ArchivePath.BaseExtension = options.ArchivePath.BaseExtension;
+ uc.ArchivePath.VolExtension = options.ArchivePath.VolExtension;
+ uc.ArchivePath.ParseFromPath(archivePath);
+ uc.ActionSet = actionSet;
+ options.Commands.Add(uc);
+ }
+ }
+ }
+}
+
+static const char kByteSymbol = 'B';
+static const char kKiloSymbol = 'K';
+static const char kMegaSymbol = 'M';
+static const char kGigaSymbol = 'G';
+
+static bool ParseComplexSize(const UString &src, UInt64 &result)
+{
+ UString s = src;
+ s.MakeUpper();
+
+ const wchar_t *start = s;
+ const wchar_t *end;
+ UInt64 number = ConvertStringToUInt64(start, &end);
+ int numDigits = (int)(end - start);
+ if (numDigits == 0 || s.Length() > numDigits + 1)
+ return false;
+ if (s.Length() == numDigits)
+ {
+ result = number;
+ return true;
+ }
+ int numBits;
+ switch (s[numDigits])
+ {
+ case kByteSymbol:
+ result = number;
+ return true;
+ case kKiloSymbol:
+ numBits = 10;
+ break;
+ case kMegaSymbol:
+ numBits = 20;
+ break;
+ case kGigaSymbol:
+ numBits = 30;
+ break;
+ default:
+ return false;
+ }
+ if (number >= ((UInt64)1 << (64 - numBits)))
+ return false;
+ result = number << numBits;
+ return true;
+}
+
+static void SetAddCommandOptions(
+ NCommandType::EEnum commandType,
+ const CParser &parser,
+ CUpdateOptions &options)
+{
+ NUpdateArchive::CActionSet defaultActionSet;
+ switch(commandType)
+ {
+ case NCommandType::kAdd:
+ defaultActionSet = NUpdateArchive::kAddActionSet;
+ break;
+ case NCommandType::kDelete:
+ defaultActionSet = NUpdateArchive::kDeleteActionSet;
+ break;
+ default:
+ defaultActionSet = NUpdateArchive::kUpdateActionSet;
+ }
+
+ options.UpdateArchiveItself = true;
+
+ options.Commands.Clear();
+ CUpdateArchiveCommand updateMainCommand;
+ updateMainCommand.ActionSet = defaultActionSet;
+ options.Commands.Add(updateMainCommand);
+ if(parser[NKey::kUpdate].ThereIs)
+ ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings,
+ defaultActionSet);
+ if(parser[NKey::kWorkingDir].ThereIs)
+ {
+ const UString &postString = parser[NKey::kWorkingDir].PostStrings[0];
+ if (postString.IsEmpty())
+ NDirectory::MyGetTempPath(options.WorkingDir);
+ else
+ options.WorkingDir = postString;
+ }
+ options.SfxMode = parser[NKey::kSfx].ThereIs;
+ if (options.SfxMode)
+ options.SfxModule = parser[NKey::kSfx].PostStrings[0];
+
+ if (parser[NKey::kVolume].ThereIs)
+ {
+ const UStringVector &sv = parser[NKey::kVolume].PostStrings;
+ for (int i = 0; i < sv.Size(); i++)
+ {
+ UInt64 size;
+ if (!ParseComplexSize(sv[i], size))
+ ThrowException("Incorrect volume size");
+ options.VolumesSizes.Add(size);
+ }
+ }
+}
+
+static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties)
+{
+ if (parser[NKey::kProperty].ThereIs)
+ {
+ // options.MethodMode.Properties.Clear();
+ for(int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
+ {
+ CProperty property;
+ const UString &postString = parser[NKey::kProperty].PostStrings[i];
+ int index = postString.Find(L'=');
+ if (index < 0)
+ property.Name = postString;
+ else
+ {
+ property.Name = postString.Left(index);
+ property.Value = postString.Mid(index + 1);
+ }
+ properties.Add(property);
+ }
+ }
+}
+
+
+static void SetArchiveType(const UString &archiveType,
+#ifndef EXCLUDE_COM
+ UString &filePath, CLSID &classID,
+#else
+ UString &formatName,
+#endif
+ UString &archiveExtension)
+{
+ CObjectVector<CArchiverInfo> archiverInfoVector;
+ ReadArchiverInfoList(archiverInfoVector);
+ if (archiverInfoVector.Size() == 0)
+ ThrowException("There are no installed archive handlers");
+ if (archiveType.IsEmpty())
+ ThrowException("Incorrect archive type was assigned");
+ for (int i = 0; i < archiverInfoVector.Size(); i++)
+ {
+ const CArchiverInfo &archiverInfo = archiverInfoVector[i];
+ if (archiverInfo.Name.CompareNoCase(archiveType) == 0)
+ {
+ #ifndef EXCLUDE_COM
+ classID = archiverInfo.ClassID;
+ filePath = archiverInfo.FilePath;
+ #else
+ formatName = archiverInfo.Name;
+
+ #endif
+
+ archiveExtension = archiverInfo.GetMainExtension();
+ return;
+ }
+ }
+ ThrowException("Incorrect archive type was assigned");
+}
+
+
+CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(kNumSwitches) {}
+
+void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings,
+ CArchiveCommandLineOptions &options)
+{
+ try
+ {
+ parser.ParseStrings(kSwitchForms, commandStrings);
+ }
+ catch(...)
+ {
+ ThrowUserErrorException();
+ }
+
+ options.IsInTerminal = (_isatty(_fileno(stdin)) != 0);
+ options.IsStdOutTerminal = (_isatty(_fileno(stdout)) != 0);
+ options.IsStdErrTerminal = (_isatty(_fileno(stderr)) != 0);
+ options.StdOutMode = parser[NKey::kStdOut].ThereIs;
+ options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;
+ options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs;
+
+ #ifdef _WIN32
+ options.LargePages = false;
+ if (parser[NKey::kLargePages].ThereIs)
+ {
+ const UString &postString = parser[NKey::kLargePages].PostStrings.Front();
+ if (postString.IsEmpty())
+ options.LargePages = true;
+ }
+ #endif
+}
+
+struct CCodePagePair
+{
+ const wchar_t *Name;
+ UINT CodePage;
+};
+
+static CCodePagePair g_CodePagePairs[] =
+{
+ { L"UTF-8", CP_UTF8 },
+ { L"WIN", CP_ACP },
+ { L"DOS", CP_OEMCP }
+};
+
+static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]);
+
+void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
+{
+ const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
+ int numNonSwitchStrings = nonSwitchStrings.Size();
+ if(numNonSwitchStrings < kMinNonSwitchWords)
+ ThrowUserErrorException();
+
+ if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
+ ThrowUserErrorException();
+
+ options.TechMode = parser[NKey::kTechMode].ThereIs;
+
+ NRecursedType::EEnum recursedType;
+ if (parser[NKey::kRecursed].ThereIs)
+ recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);
+ else
+ recursedType = NRecursedType::kNonRecursed;
+
+ UINT codePage = CP_UTF8;
+ if (parser[NKey::kCharSet].ThereIs)
+ {
+ UString name = parser[NKey::kCharSet].PostStrings.Front();
+ name.MakeUpper();
+ int i;
+ for (i = 0; i < kNumCodePages; i++)
+ {
+ const CCodePagePair &pair = g_CodePagePairs[i];
+ if (name.Compare(pair.Name) == 0)
+ {
+ codePage = pair.CodePage;
+ break;
+ }
+ }
+ if (i >= kNumCodePages)
+ ThrowUserErrorException();
+ }
+
+ bool thereAreSwitchIncludes = false;
+ if (parser[NKey::kInclude].ThereIs)
+ {
+ thereAreSwitchIncludes = true;
+ AddSwitchWildCardsToCensor(options.WildcardCensor,
+ parser[NKey::kInclude].PostStrings, true, recursedType, codePage);
+ }
+ if (parser[NKey::kExclude].ThereIs)
+ AddSwitchWildCardsToCensor(options.WildcardCensor,
+ parser[NKey::kExclude].PostStrings, false, recursedType, codePage);
+
+ int curCommandIndex = kCommandIndex + 1;
+ bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs;
+ if (thereIsArchiveName)
+ {
+ if(curCommandIndex >= numNonSwitchStrings)
+ ThrowUserErrorException();
+ options.ArchiveName = nonSwitchStrings[curCommandIndex++];
+ }
+
+ AddToCensorFromNonSwitchesStrings(
+ curCommandIndex, options.WildcardCensor,
+ nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage);
+
+ options.YesToAll = parser[NKey::kYes].ThereIs;
+
+ bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
+
+ options.PasswordEnabled = parser[NKey::kPassword].ThereIs;
+
+ if(options.PasswordEnabled)
+ options.Password = parser[NKey::kPassword].PostStrings[0];
+
+ options.StdInMode = parser[NKey::kStdIn].ThereIs;
+ options.ShowDialog = parser[NKey::kShowDialog].ThereIs;
+
+ if(isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
+ {
+ if (options.StdInMode)
+ ThrowException("Reading archives from stdin is not implemented");
+ if (!options.WildcardCensor.AllAreRelative())
+ ThrowException("Cannot use absolute pathnames for this command");
+
+ NWildcard::CCensor archiveWildcardCensor;
+
+ if (parser[NKey::kArInclude].ThereIs)
+ {
+ AddSwitchWildCardsToCensor(archiveWildcardCensor,
+ parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage);
+ }
+ if (parser[NKey::kArExclude].ThereIs)
+ AddSwitchWildCardsToCensor(archiveWildcardCensor,
+ parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage);
+
+ if (thereIsArchiveName)
+ AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);
+
+ #ifdef _WIN32
+ ConvertToLongNames(archiveWildcardCensor);
+ #endif
+
+ archiveWildcardCensor.ExtendExclude();
+
+ CObjectVector<CDirItem> dirItems;
+ {
+ UStringVector errorPaths;
+ CRecordVector<DWORD> errorCodes;
+ HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes);
+ if (res != S_OK || errorPaths.Size() > 0)
+ throw "cannot find archive";
+ }
+ UStringVector archivePaths;
+ int i;
+ for (i = 0; i < dirItems.Size(); i++)
+ {
+ const CDirItem &dirItem = dirItems[i];
+ if (!dirItem.IsDirectory())
+ archivePaths.Add(dirItem.FullPath);
+ }
+
+ if (archivePaths.Size() == 0)
+ throw "there is no such archive";
+
+ UStringVector archivePathsFull;
+
+ for (i = 0; i < archivePaths.Size(); i++)
+ {
+ UString fullPath;
+ NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath);
+ archivePathsFull.Add(fullPath);
+ }
+ CIntVector indices;
+ SortStringsToIndices(archivePathsFull, indices);
+ options.ArchivePathsSorted.Reserve(indices.Size());
+ options.ArchivePathsFullSorted.Reserve(indices.Size());
+ for (i = 0; i < indices.Size(); i++)
+ {
+ options.ArchivePathsSorted.Add(archivePaths[indices[i]]);
+ options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]);
+ }
+
+ if (isExtractGroupCommand)
+ {
+ SetMethodOptions(parser, options.ExtractProperties);
+ if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal)
+ throw kSameTerminalError;
+ if(parser[NKey::kOutputDir].ThereIs)
+ {
+ options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];
+ NFile::NName::NormalizeDirPathPrefix(options.OutputDir);
+ }
+
+ options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
+ if(parser[NKey::kOverwrite].ThereIs)
+ options.OverwriteMode =
+ k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
+ else if (options.YesToAll)
+ options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
+ }
+ }
+ else if(options.Command.IsFromUpdateGroup())
+ {
+ CUpdateOptions &updateOptions = options.UpdateOptions;
+
+ UString archiveType;
+ if(parser[NKey::kArchiveType].ThereIs)
+ archiveType = parser[NKey::kArchiveType].PostStrings[0];
+ else
+ archiveType = kDefaultArchiveType;
+
+ UString typeExtension;
+ if (!archiveType.IsEmpty())
+ {
+ #ifndef EXCLUDE_COM
+ SetArchiveType(archiveType, updateOptions.MethodMode.FilePath,
+ updateOptions.MethodMode.ClassID, typeExtension);
+ #else
+ SetArchiveType(archiveType, updateOptions.MethodMode.Name, typeExtension);
+ #endif
+ }
+ UString extension = typeExtension;
+ if(parser[NKey::kSfx].ThereIs)
+ extension = kSFXExtension;
+ updateOptions.ArchivePath.BaseExtension = extension;
+ updateOptions.ArchivePath.VolExtension = typeExtension;
+ updateOptions.ArchivePath.ParseFromPath(options.ArchiveName);
+ SetAddCommandOptions(options.Command.CommandType, parser, updateOptions);
+
+ SetMethodOptions(parser, updateOptions.MethodMode.Properties);
+
+ options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;
+
+ if (options.EnablePercents)
+ {
+ if ((options.StdOutMode && !options.IsStdErrTerminal) ||
+ (!options.StdOutMode && !options.IsStdOutTerminal))
+ options.EnablePercents = false;
+ }
+
+ updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;
+ if (updateOptions.EMailMode)
+ {
+ updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();
+ if (updateOptions.EMailAddress.Length() > 0)
+ if (updateOptions.EMailAddress[0] == L'.')
+ {
+ updateOptions.EMailRemoveAfter = true;
+ updateOptions.EMailAddress.Delete(0);
+ }
+ }
+
+ updateOptions.StdOutMode = options.StdOutMode;
+ updateOptions.StdInMode = options.StdInMode;
+
+ if (updateOptions.StdOutMode && updateOptions.EMailMode)
+ throw "stdout mode and email mode cannot be combined";
+ if (updateOptions.StdOutMode && options.IsStdOutTerminal)
+ throw kTerminalOutError;
+ if(updateOptions.StdInMode)
+ updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();
+
+ #ifdef _WIN32
+ ConvertToLongNames(options.WildcardCensor);
+ #endif
+ }
+ else
+ ThrowUserErrorException();
+ options.WildcardCensor.ExtendExclude();
+}
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h
new file mode 100755
index 00000000..daa66fb6
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -0,0 +1,95 @@
+// ArchiveCommandLine.h
+
+#ifndef __ARCHIVECOMMANDLINE_H
+#define __ARCHIVECOMMANDLINE_H
+
+#include "Common/Wildcard.h"
+#include "Common/CommandLineParser.h"
+
+#include "Extract.h"
+#include "Update.h"
+
+struct CArchiveCommandLineException: public AString
+{
+ CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {}
+};
+
+namespace NCommandType { enum EEnum
+{
+ kAdd = 0,
+ kUpdate,
+ kDelete,
+ kTest,
+ kExtract,
+ kFullExtract,
+ kList
+};}
+
+namespace NRecursedType { enum EEnum
+{
+ kRecursed,
+ kWildCardOnlyRecursed,
+ kNonRecursed,
+};}
+
+struct CArchiveCommand
+{
+ NCommandType::EEnum CommandType;
+ bool IsFromExtractGroup() const;
+ bool IsFromUpdateGroup() const;
+ bool IsTestMode() const { return CommandType == NCommandType::kTest; }
+ NExtract::NPathMode::EEnum GetPathMode() const;
+};
+
+struct CArchiveCommandLineOptions
+{
+ bool HelpMode;
+
+ #ifdef _WIN32
+ bool LargePages;
+ #endif
+
+ bool IsInTerminal;
+ bool IsStdOutTerminal;
+ bool IsStdErrTerminal;
+ bool StdInMode;
+ bool StdOutMode;
+ bool EnableHeaders;
+
+ bool YesToAll;
+ bool ShowDialog;
+ // NWildcard::CCensor ArchiveWildcardCensor;
+ NWildcard::CCensor WildcardCensor;
+
+ CArchiveCommand Command;
+ UString ArchiveName;
+
+ bool PasswordEnabled;
+ UString Password;
+
+ bool TechMode;
+ // Extract
+ bool AppendName;
+ UString OutputDir;
+ NExtract::NOverwriteMode::EEnum OverwriteMode;
+ UStringVector ArchivePathsSorted;
+ UStringVector ArchivePathsFullSorted;
+ CObjectVector<CProperty> ExtractProperties;
+
+ CUpdateOptions UpdateOptions;
+ bool EnablePercents;
+
+ CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {};
+
+};
+
+class CArchiveCommandLineParser
+{
+ NCommandLineParser::CParser parser;
+public:
+ CArchiveCommandLineParser();
+ void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options);
+ void Parse2(CArchiveCommandLineOptions &options);
+};
+
+#endif
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
new file mode 100755
index 00000000..05520fed
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -0,0 +1,448 @@
+// ArchiveExtractCallback.cpp
+
+#include "StdAfx.h"
+
+#include "ArchiveExtractCallback.h"
+
+#include "Common/Wildcard.h"
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/FileFind.h"
+#include "Windows/Time.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+
+#include "Windows/PropVariantConversions.h"
+
+#include "../../Common/FilePathAutoRename.h"
+
+#include "../Common/ExtractingFilePath.h"
+#include "OpenArchive.h"
+
+using namespace NWindows;
+
+static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name";
+static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file ";
+static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";
+
+
+void CArchiveExtractCallback::Init(
+ IInArchive *archiveHandler,
+ IFolderArchiveExtractCallback *extractCallback2,
+ bool stdOutMode,
+ const UString &directoryPath,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const UStringVector &removePathParts,
+ const UString &itemDefaultName,
+ const FILETIME &utcLastWriteTimeDefault,
+ UInt32 attributesDefault)
+{
+ _stdOutMode = stdOutMode;
+ _numErrors = 0;
+ _extractCallback2 = extractCallback2;
+ _itemDefaultName = itemDefaultName;
+ _utcLastWriteTimeDefault = utcLastWriteTimeDefault;
+ _attributesDefault = attributesDefault;
+ _removePathParts = removePathParts;
+ _pathMode = pathMode;
+ _overwriteMode = overwriteMode;
+ _archiveHandler = archiveHandler;
+ _directoryPath = directoryPath;
+ NFile::NName::NormalizeDirPathPrefix(_directoryPath);
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)
+{
+ COM_TRY_BEGIN
+ return _extractCallback2->SetTotal(size);
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)
+{
+ COM_TRY_BEGIN
+ return _extractCallback2->SetCompleted(completeValue);
+ COM_TRY_END
+}
+
+void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath)
+{
+ fullPath = _directoryPath;
+ for(int i = 0; i < dirPathParts.Size(); i++)
+ {
+ if (i > 0)
+ fullPath += wchar_t(NFile::NName::kDirDelimiter);
+ fullPath += dirPathParts[i];
+ NFile::NDirectory::MyCreateDirectory(fullPath);
+ }
+}
+
+static UString MakePathNameFromParts(const UStringVector &parts)
+{
+ UString result;
+ for(int i = 0; i < parts.Size(); i++)
+ {
+ if(i != 0)
+ result += wchar_t(NFile::NName::kDirDelimiter);
+ result += parts[i];
+ }
+ return result;
+}
+
+
+HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
+{
+ filetimeIsDefined = false;
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, propID, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ filetime = prop.filetime;
+ filetimeIsDefined = true;
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
+{
+ COM_TRY_BEGIN
+ *outStream = 0;
+ _outFileStream.Release();
+
+ _encrypted = false;
+ _isSplit = false;
+
+ UString fullPath;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));
+
+ if(prop.vt == VT_EMPTY)
+ fullPath = _itemDefaultName;
+ else
+ {
+ if(prop.vt != VT_BSTR)
+ return E_FAIL;
+ fullPath = prop.bstrVal;
+ }
+ }
+
+ // UString fullPathCorrect = GetCorrectPath(fullPath);
+ _filePath = fullPath;
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop));
+ if (prop.vt != VT_EMPTY)
+ {
+ if (prop.vt != VT_UI8)
+ return E_FAIL;
+ _position = prop.uhVal.QuadPart;
+ _isSplit = true;
+ }
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidEncrypted, &prop));
+ if (prop.vt == VT_BOOL)
+ _encrypted = VARIANT_BOOLToBool(prop.boolVal);
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ }
+
+ if(askExtractMode == NArchive::NExtract::NAskMode::kExtract)
+ {
+ if (_stdOutMode)
+ {
+ CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream;
+ *outStream = outStreamLoc.Detach();
+ return S_OK;
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &prop));
+ if (prop.vt == VT_EMPTY)
+ {
+ _processedFileInfo.Attributes = _attributesDefault;
+ _processedFileInfo.AttributesAreDefined = false;
+ }
+ else
+ {
+ if (prop.vt != VT_UI4)
+ throw "incorrect item";
+ _processedFileInfo.Attributes = prop.ulVal;
+ _processedFileInfo.AttributesAreDefined = true;
+ }
+ }
+
+ RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory));
+
+ RINOK(GetTime(index, kpidCreationTime, _processedFileInfo.CreationTime,
+ _processedFileInfo.IsCreationTimeDefined));
+ RINOK(GetTime(index, kpidLastWriteTime, _processedFileInfo.LastWriteTime,
+ _processedFileInfo.IsLastWriteTimeDefined));
+ RINOK(GetTime(index, kpidLastAccessTime, _processedFileInfo.LastAccessTime,
+ _processedFileInfo.IsLastAccessTimeDefined));
+
+ bool newFileSizeDefined;
+ UInt64 newFileSize;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop));
+ newFileSizeDefined = (prop.vt != VT_EMPTY);
+ if (newFileSizeDefined)
+ newFileSize = ConvertPropVariantToUInt64(prop);
+ }
+
+ bool isAnti = false;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &prop));
+ if (prop.vt == VT_BOOL)
+ isAnti = VARIANT_BOOLToBool(prop.boolVal);
+ }
+
+ UStringVector pathParts;
+ SplitPathToParts(fullPath, pathParts);
+
+ if(pathParts.IsEmpty())
+ return E_FAIL;
+ UString processedPath;
+ switch(_pathMode)
+ {
+ case NExtract::NPathMode::kFullPathnames:
+ {
+ processedPath = fullPath;
+ break;
+ }
+ case NExtract::NPathMode::kCurrentPathnames:
+ {
+ // for incorrect paths: "/dir1/dir2/file"
+ int numRemovePathParts = _removePathParts.Size();
+ if(pathParts.Size() <= numRemovePathParts)
+ return E_FAIL;
+ for(int i = 0; i < numRemovePathParts; i++)
+ if(_removePathParts[i].CompareNoCase(pathParts[i]) != 0)
+ return E_FAIL;
+ pathParts.Delete(0, numRemovePathParts);
+ processedPath = MakePathNameFromParts(pathParts);
+ break;
+ }
+ case NExtract::NPathMode::kNoPathnames:
+ {
+ processedPath = pathParts.Back();
+ pathParts.Delete(0, pathParts.Size() - 1); // Test it!!
+ break;
+ }
+ }
+ processedPath = GetCorrectPath(processedPath);
+ if(!_processedFileInfo.IsDirectory)
+ pathParts.DeleteBack();
+
+ MakeCorrectPath(pathParts);
+
+ if (!isAnti)
+ {
+ if (!pathParts.IsEmpty())
+ {
+ UString fullPathNew;
+ CreateComplexDirectory(pathParts, fullPathNew);
+ if (_processedFileInfo.IsDirectory)
+ NFile::NDirectory::SetDirTime(fullPathNew,
+ (WriteCreated && _processedFileInfo.IsCreationTimeDefined) ? &_processedFileInfo.CreationTime : NULL,
+ (WriteAccessed && _processedFileInfo.IsLastAccessTimeDefined) ? &_processedFileInfo.LastAccessTime : NULL,
+ (WriteModified && _processedFileInfo.IsLastWriteTimeDefined) ? &_processedFileInfo.LastWriteTime : &_utcLastWriteTimeDefault);
+ }
+ }
+
+
+ UString fullProcessedPath = _directoryPath + processedPath;
+
+ if(_processedFileInfo.IsDirectory)
+ {
+ _diskFilePath = fullProcessedPath;
+ if (isAnti)
+ NFile::NDirectory::MyRemoveDirectory(_diskFilePath);
+ return S_OK;
+ }
+
+ if (!_isSplit)
+ {
+ NFile::NFind::CFileInfoW fileInfo;
+ if(NFile::NFind::FindFile(fullProcessedPath, fileInfo))
+ {
+ switch(_overwriteMode)
+ {
+ case NExtract::NOverwriteMode::kSkipExisting:
+ return S_OK;
+ case NExtract::NOverwriteMode::kAskBefore:
+ {
+ Int32 overwiteResult;
+ RINOK(_extractCallback2->AskOverwrite(
+ fullProcessedPath, &fileInfo.LastWriteTime, &fileInfo.Size, fullPath,
+ _processedFileInfo.IsLastWriteTimeDefined ? &_processedFileInfo.LastWriteTime : NULL,
+ newFileSizeDefined ? &newFileSize : NULL,
+ &overwiteResult))
+
+ switch(overwiteResult)
+ {
+ case NOverwriteAnswer::kCancel:
+ return E_ABORT;
+ case NOverwriteAnswer::kNo:
+ return S_OK;
+ case NOverwriteAnswer::kNoToAll:
+ _overwriteMode = NExtract::NOverwriteMode::kSkipExisting;
+ return S_OK;
+ case NOverwriteAnswer::kYesToAll:
+ _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
+ break;
+ case NOverwriteAnswer::kYes:
+ break;
+ case NOverwriteAnswer::kAutoRename:
+ _overwriteMode = NExtract::NOverwriteMode::kAutoRename;
+ break;
+ default:
+ throw 20413;
+ }
+ }
+ }
+ if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename)
+ {
+ if (!AutoRenamePath(fullProcessedPath))
+ {
+ UString message = UString(kCantAutoRename) + fullProcessedPath;
+ RINOK(_extractCallback2->MessageError(message));
+ return E_FAIL;
+ }
+ }
+ else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting)
+ {
+ UString existPath = fullProcessedPath;
+ if (!AutoRenamePath(existPath))
+ {
+ UString message = kCantAutoRename + fullProcessedPath;
+ RINOK(_extractCallback2->MessageError(message));
+ return E_FAIL;
+ }
+ if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath))
+ {
+ UString message = UString(kCantRenameFile) + fullProcessedPath;
+ RINOK(_extractCallback2->MessageError(message));
+ return E_FAIL;
+ }
+ }
+ else
+ if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
+ {
+ UString message = UString(kCantDeleteOutputFile) +
+ fullProcessedPath;
+ RINOK(_extractCallback2->MessageError(message));
+ return E_FAIL;
+ }
+ }
+ }
+ if (!isAnti)
+ {
+ _outFileStreamSpec = new COutFileStream;
+ CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
+ if (!_outFileStreamSpec->File.Open(fullProcessedPath,
+ _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))
+ {
+ // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
+ {
+ UString message = L"can not open output file " + fullProcessedPath;
+ RINOK(_extractCallback2->MessageError(message));
+ return S_OK;
+ }
+ }
+ if (_isSplit)
+ {
+ RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
+ }
+ _outFileStream = outStreamLoc;
+ *outStream = outStreamLoc.Detach();
+ }
+ _diskFilePath = fullProcessedPath;
+ }
+ else
+ {
+ *outStream = NULL;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
+{
+ COM_TRY_BEGIN
+ _extractMode = false;
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract:
+ _extractMode = true;
+ };
+ return _extractCallback2->PrepareOperation(_filePath, askExtractMode, _isSplit ? &_position: 0);
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
+{
+ COM_TRY_BEGIN
+ switch(operationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kOK:
+ case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
+ case NArchive::NExtract::NOperationResult::kCRCError:
+ case NArchive::NExtract::NOperationResult::kDataError:
+ break;
+ default:
+ _outFileStream.Release();
+ return E_FAIL;
+ }
+ if(_outFileStream != NULL)
+ _outFileStreamSpec->File.SetTime(
+ (WriteCreated && _processedFileInfo.IsCreationTimeDefined) ? &_processedFileInfo.CreationTime : NULL,
+ (WriteAccessed && _processedFileInfo.IsLastAccessTimeDefined) ? &_processedFileInfo.LastAccessTime : NULL,
+ (WriteModified && _processedFileInfo.IsLastWriteTimeDefined) ? &_processedFileInfo.LastWriteTime : &_utcLastWriteTimeDefault);
+ _outFileStream.Release();
+ if (_extractMode && _processedFileInfo.AttributesAreDefined)
+ NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes);
+ RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));
+ return S_OK;
+ COM_TRY_END
+}
+
+/*
+STDMETHODIMP CArchiveExtractCallback::GetInStream(
+ const wchar_t *name, ISequentialInStream **inStream)
+{
+ COM_TRY_BEGIN
+ CInFileStream *inFile = new CInFileStream;
+ CMyComPtr<ISequentialInStream> inStreamTemp = inFile;
+ if (!inFile->Open(_srcDirectoryPrefix + name))
+ return ::GetLastError();
+ *inStream = inStreamTemp.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+*/
+
+STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
+{
+ COM_TRY_BEGIN
+ if (!_cryptoGetTextPassword)
+ {
+ RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword,
+ &_cryptoGetTextPassword));
+ }
+ return _cryptoGetTextPassword->CryptoGetTextPassword(password);
+ COM_TRY_END
+}
+
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
new file mode 100755
index 00000000..4fd63a53
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -0,0 +1,111 @@
+// ArchiveExtractCallback.h
+
+#ifndef __ARCHIVEEXTRACTCALLBACK_H
+#define __ARCHIVEEXTRACTCALLBACK_H
+
+#include "../../Archive/IArchive.h"
+#include "IFileExtractCallback.h"
+
+#include "Common/String.h"
+#include "Common/MyCom.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../IPassword.h"
+
+#include "ExtractMode.h"
+
+class CArchiveExtractCallback:
+ public IArchiveExtractCallback,
+ // public IArchiveVolumeExtractCallback,
+ public ICryptoGetTextPassword,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
+ // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)
+
+ // IProgress
+ STDMETHOD(SetTotal)(UInt64 size);
+ STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+ // IExtractCallBack
+ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode);
+ STDMETHOD(PrepareOperation)(Int32 askExtractMode);
+ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);
+
+ // IArchiveVolumeExtractCallback
+ // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream);
+
+ // ICryptoGetTextPassword
+ STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);
+
+private:
+ CMyComPtr<IInArchive> _archiveHandler;
+ CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
+ CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
+ UString _directoryPath;
+ NExtract::NPathMode::EEnum _pathMode;
+ NExtract::NOverwriteMode::EEnum _overwriteMode;
+
+ UString _filePath;
+ UInt64 _position;
+ bool _isSplit;
+
+ UString _diskFilePath;
+
+ bool _extractMode;
+
+ bool WriteModified;
+ bool WriteCreated;
+ bool WriteAccessed;
+
+ bool _encrypted;
+
+ struct CProcessedFileInfo
+ {
+ FILETIME CreationTime;
+ FILETIME LastWriteTime;
+ FILETIME LastAccessTime;
+ UInt32 Attributes;
+
+ bool IsCreationTimeDefined;
+ bool IsLastWriteTimeDefined;
+ bool IsLastAccessTimeDefined;
+
+ bool IsDirectory;
+ bool AttributesAreDefined;
+ } _processedFileInfo;
+
+ COutFileStream *_outFileStreamSpec;
+ CMyComPtr<ISequentialOutStream> _outFileStream;
+ UStringVector _removePathParts;
+
+ UString _itemDefaultName;
+ FILETIME _utcLastWriteTimeDefault;
+ UInt32 _attributesDefault;
+ bool _stdOutMode;
+
+ void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath);
+ HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
+public:
+ CArchiveExtractCallback():
+ WriteModified(true),
+ WriteCreated(false),
+ WriteAccessed(false)
+ {}
+ void Init(
+ IInArchive *archiveHandler,
+ IFolderArchiveExtractCallback *extractCallback2,
+ bool stdOutMode,
+ const UString &directoryPath,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const UStringVector &removePathParts,
+ const UString &itemDefaultName,
+ const FILETIME &utcLastWriteTimeDefault,
+ UInt32 attributesDefault);
+
+ UInt64 _numErrors;
+};
+
+#endif
diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp
new file mode 100755
index 00000000..2d50ede1
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveName.cpp
@@ -0,0 +1,46 @@
+// ArchiveName.cpp
+
+#include "StdAfx.h"
+
+#include "Windows/FileFind.h"
+#include "Windows/FileDir.h"
+
+using namespace NWindows;
+
+UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName)
+{
+ UString resultName = L"Archive";
+ if (fromPrev)
+ {
+ UString dirPrefix;
+ if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix))
+ {
+ if (dirPrefix.Length() > 0)
+ if (dirPrefix[dirPrefix.Length() - 1] == '\\')
+ {
+ dirPrefix.Delete(dirPrefix.Length() - 1);
+ NFile::NFind::CFileInfoW fileInfo;
+ if (NFile::NFind::FindFile(dirPrefix, fileInfo))
+ resultName = fileInfo.Name;
+ }
+ }
+ }
+ else
+ {
+ NFile::NFind::CFileInfoW fileInfo;
+ if (!NFile::NFind::FindFile(srcName, fileInfo))
+ return resultName;
+ resultName = fileInfo.Name;
+ if (!fileInfo.IsDirectory() && !keepName)
+ {
+ int dotPos = resultName.ReverseFind('.');
+ if (dotPos > 0)
+ {
+ UString archiveName2 = resultName.Left(dotPos);
+ if (archiveName2.ReverseFind('.') < 0)
+ resultName = archiveName2;
+ }
+ }
+ }
+ return resultName;
+}
diff --git a/CPP/7zip/UI/Common/ArchiveName.h b/CPP/7zip/UI/Common/ArchiveName.h
new file mode 100755
index 00000000..6b001a5a
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveName.h
@@ -0,0 +1,10 @@
+// ArchiveName.h
+
+#ifndef __ARCHIVENAME_H
+#define __ARCHIVENAME_H
+
+#include "Common/String.h"
+
+UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName);
+
+#endif
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
new file mode 100755
index 00000000..1d2944d8
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -0,0 +1,127 @@
+// ArchiveOpenCallback.cpp
+
+#include "StdAfx.h"
+
+#include "ArchiveOpenCallback.h"
+
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+
+#include "../../Common/FileStreams.h"
+
+using namespace NWindows;
+
+STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
+{
+ COM_TRY_BEGIN
+ return Callback->SetTotal(files, bytes);
+ COM_TRY_END
+}
+
+STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
+{
+ COM_TRY_BEGIN
+ return Callback->SetTotal(files, bytes);
+ COM_TRY_END
+}
+
+STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant propVariant;
+ if (_subArchiveMode)
+ {
+ switch(propID)
+ {
+ case kpidName:
+ propVariant = _subArchiveName;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ }
+ switch(propID)
+ {
+ case kpidName:
+ propVariant = _fileInfo.Name;
+ break;
+ case kpidIsFolder:
+ propVariant = _fileInfo.IsDirectory();
+ break;
+ case kpidSize:
+ propVariant = _fileInfo.Size;
+ break;
+ case kpidAttributes:
+ propVariant = (UInt32)_fileInfo.Attributes;
+ break;
+ case kpidLastAccessTime:
+ propVariant = _fileInfo.LastAccessTime;
+ break;
+ case kpidCreationTime:
+ propVariant = _fileInfo.CreationTime;
+ break;
+ case kpidLastWriteTime:
+ propVariant = _fileInfo.LastWriteTime;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+int COpenCallbackImp::FindName(const UString &name)
+{
+ for (int i = 0; i < FileNames.Size(); i++)
+ if (name.CompareNoCase(FileNames[i]) == 0)
+ return i;
+ return -1;
+}
+
+struct CInFileStreamVol: public CInFileStream
+{
+ UString Name;
+ COpenCallbackImp *OpenCallbackImp;
+ CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
+ ~CInFileStreamVol()
+ {
+ int index = OpenCallbackImp->FindName(Name);
+ if (index >= 0)
+ OpenCallbackImp->FileNames.Delete(index);
+ }
+};
+
+STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)
+{
+ COM_TRY_BEGIN
+ if (_subArchiveMode)
+ return S_FALSE;
+ RINOK(Callback->CheckBreak());
+ *inStream = NULL;
+ UString fullPath = _folderPrefix + name;
+ if (!NFile::NFind::FindFile(fullPath, _fileInfo))
+ return S_FALSE;
+ if (_fileInfo.IsDirectory())
+ return S_FALSE;
+ CInFileStreamVol *inFile = new CInFileStreamVol;
+ CMyComPtr<IInStream> inStreamTemp = inFile;
+ if (!inFile->Open(fullPath))
+ return ::GetLastError();
+ *inStream = inStreamTemp.Detach();
+ inFile->Name = name;
+ inFile->OpenCallbackImp = this;
+ inFile->OpenCallbackRef = this;
+ FileNames.Add(name);
+ return S_OK;
+ COM_TRY_END
+}
+
+#ifndef _NO_CRYPTO
+STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
+{
+ COM_TRY_BEGIN
+ return Callback->CryptoGetTextPassword(password);
+ COM_TRY_END
+}
+#endif
+
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
new file mode 100755
index 00000000..454873ad
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
@@ -0,0 +1,89 @@
+// ArchiveOpenCallback.h
+
+#ifndef __ARCHIVE_OPEN_CALLBACK_H
+#define __ARCHIVE_OPEN_CALLBACK_H
+
+#include "Common/String.h"
+#include "Common/MyCom.h"
+#include "Windows/FileFind.h"
+
+#ifndef _NO_CRYPTO
+#include "../../IPassword.h"
+#endif
+#include "../../Archive/IArchive.h"
+
+struct IOpenCallbackUI
+{
+ virtual HRESULT CheckBreak() = 0;
+ virtual HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes) = 0;
+ virtual HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes) = 0;
+ #ifndef _NO_CRYPTO
+ virtual HRESULT CryptoGetTextPassword(BSTR *password) = 0;
+ virtual HRESULT GetPasswordIfAny(UString &password) = 0;
+ virtual bool WasPasswordAsked() = 0;
+ virtual void ClearPasswordWasAskedFlag() = 0;
+ #endif
+};
+
+class COpenCallbackImp:
+ public IArchiveOpenCallback,
+ public IArchiveOpenVolumeCallback,
+ public IArchiveOpenSetSubArchiveName,
+ #ifndef _NO_CRYPTO
+ public ICryptoGetTextPassword,
+ #endif
+ public CMyUnknownImp
+{
+public:
+ #ifndef _NO_CRYPTO
+ MY_UNKNOWN_IMP3(
+ IArchiveOpenVolumeCallback,
+ ICryptoGetTextPassword,
+ IArchiveOpenSetSubArchiveName
+ )
+ #else
+ MY_UNKNOWN_IMP2(
+ IArchiveOpenVolumeCallback,
+ IArchiveOpenSetSubArchiveName
+ )
+ #endif
+
+ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
+ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
+
+ // IArchiveOpenVolumeCallback
+ STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
+ STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
+
+ #ifndef _NO_CRYPTO
+ // ICryptoGetTextPassword
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+ #endif
+
+ STDMETHOD(SetSubArchiveName(const wchar_t *name))
+ {
+ _subArchiveMode = true;
+ _subArchiveName = name;
+ return S_OK;
+ }
+
+private:
+ UString _folderPrefix;
+ NWindows::NFile::NFind::CFileInfoW _fileInfo;
+ bool _subArchiveMode;
+ UString _subArchiveName;
+public:
+ UStringVector FileNames;
+ IOpenCallbackUI *Callback;
+ void Init(const UString &folderPrefix, const UString &fileName)
+ {
+ _folderPrefix = folderPrefix;
+ if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo))
+ throw 1;
+ FileNames.Clear();
+ _subArchiveMode = false;
+ }
+ int FindName(const UString &name);
+};
+
+#endif
diff --git a/CPP/7zip/UI/Common/ArchiverInfo.cpp b/CPP/7zip/UI/Common/ArchiverInfo.cpp
new file mode 100755
index 00000000..7833ed3c
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiverInfo.cpp
@@ -0,0 +1,372 @@
+// ArchiverInfo.cpp
+
+#include "StdAfx.h"
+
+#include "ArchiverInfo.h"
+
+#ifndef EXCLUDE_COM
+
+#include "Common/StringConvert.h"
+#include "Windows/FileFind.h"
+#include "Windows/FileName.h"
+#include "Windows/DLL.h"
+#ifdef _WIN32
+#include "Windows/Registry.h"
+#endif
+#include "Windows/PropVariant.h"
+#include "../../Archive/IArchive.h"
+
+using namespace NWindows;
+using namespace NFile;
+
+#endif
+
+extern HINSTANCE g_hInstance;
+
+#ifndef EXCLUDE_COM
+
+static void SplitString(const UString &srcString, UStringVector &destStrings)
+{
+ destStrings.Clear();
+ UString string;
+ int len = srcString.Length();
+ if (len == 0)
+ return;
+ for (int i = 0; i < len; i++)
+ {
+ wchar_t c = srcString[i];
+ if (c == L' ')
+ {
+ if (!string.IsEmpty())
+ {
+ destStrings.Add(string);
+ string.Empty();
+ }
+ }
+ else
+ string += c;
+ }
+ if (!string.IsEmpty())
+ destStrings.Add(string);
+}
+
+typedef UInt32 (WINAPI * GetHandlerPropertyFunc)(
+ PROPID propID, PROPVARIANT *value);
+
+static UString GetModuleFolderPrefix()
+{
+ UString path;
+ NDLL::MyGetModuleFileName(g_hInstance, path);
+ int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR);
+ return path.Left(pos + 1);
+}
+
+static wchar_t *kFormatFolderName = L"Formats";
+
+#ifdef _WIN32
+static LPCTSTR kRegistryPath = TEXT("Software\\7-zip");
+static LPCWSTR kProgramPathValue = L"Path";
+static bool ReadPathFromRegistry(HKEY baseKey, UString &path)
+{
+ NRegistry::CKey key;
+ if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
+ if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS)
+ {
+ NName::NormalizeDirPathPrefix(path);
+ return true;
+ }
+ return false;
+}
+#endif
+
+static UString GetBaseFolderPrefixFromRegistry()
+{
+ UString moduleFolderPrefix = GetModuleFolderPrefix();
+ NFind::CFileInfoW fileInfo;
+ if (NFind::FindFile(moduleFolderPrefix + kFormatFolderName, fileInfo))
+ if (fileInfo.IsDirectory())
+ return moduleFolderPrefix;
+ UString path;
+ #ifdef _WIN32
+ if(ReadPathFromRegistry(HKEY_CURRENT_USER, path))
+ return path;
+ if(ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path))
+ return path;
+ #endif
+ return moduleFolderPrefix;
+}
+
+typedef UInt32 (WINAPI *CreateObjectPointer)(
+ const GUID *clsID,
+ const GUID *interfaceID,
+ void **outObject);
+
+#endif
+
+#ifndef _SFX
+static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size)
+{
+ bb.SetCapacity(size);
+ memmove((Byte *)bb, data, size);
+}
+#endif
+
+void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
+{
+ archivers.Clear();
+
+ #ifdef EXCLUDE_COM
+
+ #ifdef FORMAT_7Z
+ {
+ CArchiverInfo item;
+ item.UpdateEnabled = true;
+ item.Name = L"7z";
+ item.Extensions.Add(CArchiverExtInfo(L"7z"));
+ #ifndef _SFX
+ const unsigned char kSig[] = {'7' , 'z', 0xBC, 0xAF, 0x27, 0x1C};
+ SetBuffer(item.StartSignature, kSig, 6);
+ #endif
+ archivers.Add(item);
+ }
+ #endif
+
+ #ifdef FORMAT_BZIP2
+ {
+ CArchiverInfo item;
+ item.UpdateEnabled = true;
+ item.KeepName = true;
+ item.Name = L"BZip2";
+ item.Extensions.Add(CArchiverExtInfo(L"bz2"));
+ item.Extensions.Add(CArchiverExtInfo(L"tbz2", L".tar"));
+ #ifndef _SFX
+ const unsigned char sig[] = {'B' , 'Z', 'h' };
+ SetBuffer(item.StartSignature, sig, 3);
+ #endif
+ archivers.Add(item);
+ }
+ #endif
+
+ #ifdef FORMAT_CAB
+ {
+ CArchiverInfo item;
+ item.Name = L"Cab";
+ item.Extensions.Add(CArchiverExtInfo(L"cab"));
+ #ifndef _SFX
+ const unsigned char sig[] = { 0x4D, 0x53, 0x43, 0x46 };
+ SetBuffer(item.StartSignature, sig, 4);
+ #endif
+ archivers.Add(item);
+ }
+ #endif
+
+ #ifdef FORMAT_GZIP
+ {
+ CArchiverInfo item;
+ item.UpdateEnabled = true;
+ item.Name = L"GZip";
+ item.Extensions.Add(CArchiverExtInfo(L"gz"));
+ item.Extensions.Add(CArchiverExtInfo(L"tgz", L".tar"));
+ #ifndef _SFX
+ const unsigned char sig[] = { 0x1F, 0x8B };
+ SetBuffer(item.StartSignature, sig, 2);
+ #endif
+ archivers.Add(item);
+ }
+ #endif
+
+ #ifdef FORMAT_SPLIT
+ {
+ CArchiverInfo item;
+ item.UpdateEnabled = false;
+ item.KeepName = true;
+ item.Name = L"Split";
+ item.Extensions.Add(CArchiverExtInfo(L"001"));
+ archivers.Add(item);
+ }
+ #endif
+
+ #ifdef FORMAT_TAR
+ {
+ CArchiverInfo item;
+ item.UpdateEnabled = true;
+ item.Name = L"Tar";
+ item.Extensions.Add(CArchiverExtInfo(L"tar"));
+ archivers.Add(item);
+ }
+ #endif
+
+ #ifdef FORMAT_ZIP
+ {
+ CArchiverInfo item;
+ item.UpdateEnabled = true;
+ item.Name = L"Zip";
+ item.Extensions.Add(CArchiverExtInfo(L"zip"));
+ #ifndef _SFX
+ const unsigned char sig[] = { 0x50, 0x4B, 0x03, 0x04 };
+ SetBuffer(item.StartSignature, sig, 4);
+ #endif
+ archivers.Add(item);
+ }
+ #endif
+
+ #ifdef FORMAT_CPIO
+ {
+ CArchiverInfo item;
+ item.Name = L"Cpio";
+ item.Extensions.Add(CArchiverExtInfo(L"cpio"));
+ archivers.Add(item);
+ }
+ #endif
+
+ #ifdef FORMAT_RPM
+ {
+ CArchiverInfo item;
+ item.Name = L"Rpm";
+ item.Extensions.Add(CArchiverExtInfo(L"rpm", L".cpio.gz"));
+ archivers.Add(item);
+ }
+ #endif
+
+ #ifdef FORMAT_ARJ
+ {
+ CArchiverInfo item;
+ item.Name = L"Arj";
+ item.Extensions.Add(CArchiverExtInfo(L"arj"));
+ #ifndef _SFX
+ const unsigned char sig[] = { 0x60, 0xEA };
+ SetBuffer(item.StartSignature, sig, 2);
+ #endif
+ archivers.Add(item);
+ }
+ #endif
+
+ #ifdef FORMAT_Z
+ {
+ CArchiverInfo item;
+ item.Name = L"Z";
+ item.Extensions.Add(CArchiverExtInfo(L"Z"));
+ #ifndef _SFX
+ const unsigned char sig[] = { 0x1F, 0x9D };
+ SetBuffer(item.StartSignature, sig, 2);
+ #endif
+ archivers.Add(item);
+ }
+ #endif
+
+ #else
+
+ UString folderPath = GetBaseFolderPrefixFromRegistry() +
+ (UString)kFormatFolderName + (UString)WSTRING_PATH_SEPARATOR;
+ NFind::CEnumeratorW enumerator(folderPath + L"*");
+ NFind::CFileInfoW fileInfo;
+ while (enumerator.Next(fileInfo))
+ {
+ if (fileInfo.IsDirectory())
+ continue;
+ UString filePath = folderPath + fileInfo.Name;
+ {
+ NDLL::CLibrary library;
+ if (!library.LoadEx(filePath, LOAD_LIBRARY_AS_DATAFILE))
+ continue;
+ }
+
+ NDLL::CLibrary library;
+ if (!library.Load(filePath))
+ continue;
+ GetHandlerPropertyFunc getHandlerProperty = (GetHandlerPropertyFunc)
+ library.GetProcAddress("GetHandlerProperty");
+ if (getHandlerProperty == NULL)
+ continue;
+
+ CArchiverInfo item;
+ item.FilePath = filePath;
+
+ NWindows::NCOM::CPropVariant prop;
+ if (getHandlerProperty(NArchive::kName, &prop) != S_OK)
+ continue;
+ if (prop.vt != VT_BSTR)
+ continue;
+ item.Name = prop.bstrVal;
+ prop.Clear();
+
+ if (getHandlerProperty(NArchive::kClassID, &prop) != S_OK)
+ continue;
+ if (prop.vt != VT_BSTR)
+ continue;
+ item.ClassID = *(const GUID *)prop.bstrVal;
+ prop.Clear();
+
+ if (getHandlerProperty(NArchive::kExtension, &prop) != S_OK)
+ continue;
+ if (prop.vt != VT_BSTR)
+ continue;
+
+ UString ext = prop.bstrVal;
+ UString addExt;
+
+ prop.Clear();
+
+ if (getHandlerProperty(NArchive::kAddExtension, &prop) != S_OK)
+ continue;
+ if (prop.vt == VT_BSTR)
+ {
+ addExt = prop.bstrVal;
+ }
+ else if (prop.vt != VT_EMPTY)
+ continue;
+ prop.Clear();
+
+ UStringVector exts, addExts;
+ SplitString(ext, exts);
+ SplitString(addExt, addExts);
+
+ prop.Clear();
+ for (int i = 0; i < exts.Size(); i++)
+ {
+ CArchiverExtInfo extInfo;
+ extInfo.Ext = exts[i];
+ if (addExts.Size() > 0)
+ extInfo.AddExt = addExts[i];
+ if (extInfo.AddExt == L"*")
+ extInfo.AddExt.Empty();
+ item.Extensions.Add(extInfo);
+ }
+
+ if (getHandlerProperty(NArchive::kUpdate, &prop) == S_OK)
+ if (prop.vt == VT_BOOL)
+ item.UpdateEnabled = VARIANT_BOOLToBool(prop.boolVal);
+ prop.Clear();
+
+ if (item.UpdateEnabled)
+ {
+ if (getHandlerProperty(NArchive::kKeepName, &prop) == S_OK)
+ if (prop.vt == VT_BOOL)
+ item.KeepName = VARIANT_BOOLToBool(prop.boolVal);
+ prop.Clear();
+ }
+
+ if (getHandlerProperty(NArchive::kStartSignature, &prop) == S_OK)
+ {
+ if (prop.vt == VT_BSTR)
+ {
+ UINT len = ::SysStringByteLen(prop.bstrVal);
+ item.StartSignature.SetCapacity(len);
+ memmove(item.StartSignature, prop.bstrVal, len);
+ }
+ }
+ prop.Clear();
+
+ if (getHandlerProperty(NArchive::kAssociate, &prop) == S_OK)
+ if (prop.vt == VT_BOOL)
+ item.Associate = VARIANT_BOOLToBool(prop.boolVal);
+ prop.Clear();
+
+
+ archivers.Add(item);
+ }
+
+ #endif
+}
+
+
diff --git a/CPP/7zip/UI/Common/ArchiverInfo.h b/CPP/7zip/UI/Common/ArchiverInfo.h
new file mode 100755
index 00000000..3b829518
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiverInfo.h
@@ -0,0 +1,66 @@
+// ArchiverInfo.h
+
+#ifndef __ARCHIVERINFO_H
+#define __ARCHIVERINFO_H
+
+#include "Common/String.h"
+#include "Common/Types.h"
+#include "Common/Buffer.h"
+
+struct CArchiverExtInfo
+{
+ UString Ext;
+ UString AddExt;
+ CArchiverExtInfo() {}
+ CArchiverExtInfo(const UString &ext): Ext(ext) {}
+ CArchiverExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}
+};
+
+struct CArchiverInfo
+{
+ #ifndef EXCLUDE_COM
+ UString FilePath;
+ CLSID ClassID;
+ #endif
+ UString Name;
+ CObjectVector<CArchiverExtInfo> Extensions;
+ #ifndef _SFX
+ CByteBuffer StartSignature;
+ CByteBuffer FinishSignature;
+ bool Associate;
+ #endif
+ int FindExtension(const UString &ext) const
+ {
+ for (int i = 0; i < Extensions.Size(); i++)
+ if (ext.CompareNoCase(Extensions[i].Ext) == 0)
+ return i;
+ return -1;
+ }
+ UString GetAllExtensions() const
+ {
+ UString s;
+ for (int i = 0; i < Extensions.Size(); i++)
+ {
+ if (i > 0)
+ s += ' ';
+ s += Extensions[i].Ext;
+ }
+ return s;
+ }
+ const UString &GetMainExtension() const
+ {
+ return Extensions[0].Ext;
+ }
+ bool UpdateEnabled;
+ bool KeepName;
+
+ CArchiverInfo(): UpdateEnabled(false), KeepName(false)
+ #ifndef _SFX
+ ,Associate(true)
+ #endif
+ {}
+};
+
+void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers);
+
+#endif
diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp
new file mode 100755
index 00000000..86bdd297
--- /dev/null
+++ b/CPP/7zip/UI/Common/CompressCall.cpp
@@ -0,0 +1,367 @@
+// CompressCall.cpp
+
+#include "StdAfx.h"
+
+#include "CompressCall.h"
+
+#include "Common/Random.h"
+#include "Common/IntToString.h"
+#include "Common/MyCom.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/Synchronization.h"
+#include "Windows/FileMapping.h"
+#include "Windows/FileDir.h"
+
+#include "../../FileManager/ProgramLocation.h"
+#include "../../FileManager/RegistryUtils.h"
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif _UNICODE
+
+using namespace NWindows;
+
+static LPCWSTR kShowDialogSwitch = L" -ad";
+static LPCWSTR kEmailSwitch = L" -seml.";
+static LPCWSTR kMapSwitch = L" -i#";
+static LPCWSTR kArchiveNoNameSwitch = L" -an";
+static LPCWSTR kArchiveTypeSwitch = L" -t";
+static LPCWSTR kArchiveMapSwitch = L" -ai#";
+static LPCWSTR kStopSwitchParsing = L" --";
+static LPCWSTR kLargePagesDisable = L" -slp-";
+
+static void AddLagePagesSwitch(UString &params)
+{
+ if (!ReadLockMemoryEnable())
+ params += kLargePagesDisable;
+}
+
+HRESULT MyCreateProcess(const UString &params,
+ LPCWSTR curDir, bool waitFinish,
+ NWindows::NSynchronization::CEvent *event)
+{
+ const UString params2 = params;
+ PROCESS_INFORMATION processInformation;
+ BOOL result;
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ STARTUPINFOA startupInfo;
+ startupInfo.cb = sizeof(startupInfo);
+ startupInfo.lpReserved = 0;
+ startupInfo.lpDesktop = 0;
+ startupInfo.lpTitle = 0;
+ startupInfo.dwFlags = 0;
+ startupInfo.cbReserved2 = 0;
+ startupInfo.lpReserved2 = 0;
+
+ CSysString curDirA;
+ if (curDir != 0)
+ curDirA = GetSystemString(curDir);
+ result = ::CreateProcessA(NULL, (LPSTR)(LPCSTR)GetSystemString(params),
+ NULL, NULL, FALSE, 0, NULL,
+ ((curDir != 0) ? (LPCSTR)curDirA: 0),
+ &startupInfo, &processInformation);
+ }
+ else
+ #endif
+ {
+ STARTUPINFOW startupInfo;
+ startupInfo.cb = sizeof(startupInfo);
+ startupInfo.lpReserved = 0;
+ startupInfo.lpDesktop = 0;
+ startupInfo.lpTitle = 0;
+ startupInfo.dwFlags = 0;
+ startupInfo.cbReserved2 = 0;
+ startupInfo.lpReserved2 = 0;
+
+ result = ::CreateProcessW(NULL, (LPWSTR)(LPCWSTR)params,
+ NULL, NULL, FALSE, 0, NULL,
+ curDir,
+ &startupInfo, &processInformation);
+ }
+ if (result == 0)
+ return ::GetLastError();
+ else
+ {
+ ::CloseHandle(processInformation.hThread);
+ if (waitFinish)
+ WaitForSingleObject(processInformation.hProcess, INFINITE);
+ else if (event != NULL)
+ {
+ HANDLE handles[] = {processInformation.hProcess, *event };
+ ::WaitForMultipleObjects(sizeof(handles) / sizeof(handles[0]),
+ handles, FALSE, INFINITE);
+ }
+ ::CloseHandle(processInformation.hProcess);
+ }
+ return S_OK;
+}
+
+static UString GetQuotedString(const UString &s)
+{
+ return UString(L"\"") + s + UString(L"\"");
+}
+
+static UString Get7zGuiPath()
+{
+ UString path;
+ UString folder;
+ if (GetProgramFolderPath(folder))
+ path += folder;
+ path += L"7zG.exe";
+ return GetQuotedString(path);
+}
+
+static HRESULT CreateMap(const UStringVector &names,
+ const UString &id,
+ CFileMapping &fileMapping, NSynchronization::CEvent &event,
+ UString &params)
+{
+ UInt32 extraSize = 2;
+ UInt32 dataSize = 0;
+ for (int i = 0; i < names.Size(); i++)
+ dataSize += (names[i].Length() + 1) * sizeof(wchar_t);
+ UInt32 totalSize = extraSize + dataSize;
+
+ UString mappingName;
+ UString eventName;
+
+ CRandom random;
+ random.Init(GetTickCount());
+ for (;;)
+ {
+ int number = random.Generate();
+ wchar_t temp[32];
+ ConvertUInt64ToString(UInt32(number), temp);
+ mappingName = id;
+ mappingName += L"Mapping";
+ mappingName += temp;
+ if (!fileMapping.Create(INVALID_HANDLE_VALUE, NULL,
+ PAGE_READWRITE, totalSize, GetSystemString(mappingName)))
+ return E_FAIL;
+ if (::GetLastError() != ERROR_ALREADY_EXISTS)
+ break;
+ fileMapping.Close();
+ }
+
+ for (;;)
+ {
+ int number = random.Generate();
+ wchar_t temp[32];
+ ConvertUInt64ToString(UInt32(number), temp);
+ eventName = id;
+ eventName += L"MappingEndEvent";
+ eventName += temp;
+ if (!event.Create(true, false, GetSystemString(eventName)))
+ return E_FAIL;
+ if (::GetLastError() != ERROR_ALREADY_EXISTS)
+ break;
+ event.Close();
+ }
+
+ params += mappingName;
+ params += L":";
+ wchar_t string[10];
+ ConvertUInt64ToString(totalSize, string);
+ params += string;
+
+ params += L":";
+ params += eventName;
+
+ LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_WRITE, 0, totalSize);
+ if (data == NULL)
+ return E_FAIL;
+ {
+ wchar_t *curData = (wchar_t *)data;
+ *curData = 0;
+ curData++;
+ for (int i = 0; i < names.Size(); i++)
+ {
+ const UString &s = names[i];
+ memcpy(curData, (const wchar_t *)s, s.Length() * sizeof(wchar_t));
+ curData += s.Length();
+ *curData++ = L'\0';
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CompressFiles(
+ const UString &curDir,
+ const UString &archiveName,
+ const UString &archiveType,
+ const UStringVector &names,
+ // const UString &outFolder,
+ bool email,
+ bool showDialog,
+ bool waitFinish)
+{
+ /*
+ UString curDir;
+ if (names.Size() > 0)
+ {
+ NFile::NDirectory::GetOnlyDirPrefix(names[0], curDir);
+ }
+ */
+ UString params;
+ params = Get7zGuiPath();
+ params += L" a";
+ params += kMapSwitch;
+ // params += _fileNames[0];
+
+ UInt32 extraSize = 2;
+ UInt32 dataSize = 0;
+ for (int i = 0; i < names.Size(); i++)
+ dataSize += (names[i].Length() + 1) * sizeof(wchar_t);
+ UInt32 totalSize = extraSize + dataSize;
+
+ UString mappingName;
+ UString eventName;
+
+ CFileMapping fileMapping;
+ CRandom random;
+ random.Init(GetTickCount());
+ for (;;)
+ {
+ int number = random.Generate();
+ wchar_t temp[32];
+ ConvertUInt64ToString(UInt32(number), temp);
+ mappingName = L"7zCompressMapping";
+ mappingName += temp;
+ if (!fileMapping.Create(INVALID_HANDLE_VALUE, NULL,
+ PAGE_READWRITE, totalSize, GetSystemString(mappingName)))
+ {
+ // MyMessageBox(IDS_ERROR, 0x02000605);
+ return E_FAIL;
+ }
+ if (::GetLastError() != ERROR_ALREADY_EXISTS)
+ break;
+ fileMapping.Close();
+ }
+
+ NSynchronization::CEvent event;
+ for (;;)
+ {
+ int number = random.Generate();
+ wchar_t temp[32];
+ ConvertUInt64ToString(UInt32(number), temp);
+ eventName = L"7zCompressMappingEndEvent";
+ eventName += temp;
+ if (!event.Create(true, false, GetSystemString(eventName)))
+ {
+ // MyMessageBox(IDS_ERROR, 0x02000605);
+ return E_FAIL;
+ }
+ if (::GetLastError() != ERROR_ALREADY_EXISTS)
+ break;
+ event.Close();
+ }
+
+ params += mappingName;
+ params += L":";
+ wchar_t string[10];
+ ConvertUInt64ToString(totalSize, string);
+ params += string;
+
+ params += L":";
+ params += eventName;
+
+ if (!archiveType.IsEmpty())
+ {
+ params += kArchiveTypeSwitch;
+ params += archiveType;
+ }
+
+ if (email)
+ params += kEmailSwitch;
+
+ if (showDialog)
+ params += kShowDialogSwitch;
+
+ AddLagePagesSwitch(params);
+
+ params += kStopSwitchParsing;
+ params += L" ";
+
+ params += GetQuotedString(archiveName);
+
+ LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_WRITE, 0, totalSize);
+ if (data == NULL)
+ {
+ // MyMessageBox(IDS_ERROR, 0x02000605);
+ return E_FAIL;
+ }
+ try
+ {
+ wchar_t *curData = (wchar_t *)data;
+ *curData = 0;
+ curData++;
+ for (int i = 0; i < names.Size(); i++)
+ {
+ const UString &unicodeString = names[i];
+ memcpy(curData, (const wchar_t *)unicodeString ,
+ unicodeString .Length() * sizeof(wchar_t));
+ curData += unicodeString.Length();
+ *curData++ = L'\0';
+ }
+ // MessageBox(0, params, 0, 0);
+ RINOK(MyCreateProcess(params,
+ (curDir.IsEmpty()? 0: (LPCWSTR)curDir),
+ waitFinish, &event));
+ }
+ catch(...)
+ {
+ UnmapViewOfFile(data);
+ throw;
+ }
+ UnmapViewOfFile(data);
+
+
+ /*
+ CThreadCompressMain *compressor = new CThreadCompressMain();;
+ compressor->FileNames = _fileNames;
+ CThread thread;
+ if (!thread.Create(CThreadCompressMain::MyThreadFunction, compressor))
+ throw 271824;
+ */
+ return S_OK;
+}
+
+static HRESULT ExtractGroupCommand(const UStringVector &archivePaths,
+ const UString &params)
+{
+ UString params2 = params;
+ AddLagePagesSwitch(params2);
+ params2 += kArchiveNoNameSwitch;
+ params2 += kArchiveMapSwitch;
+ CFileMapping fileMapping;
+ NSynchronization::CEvent event;
+ RINOK(CreateMap(archivePaths, L"7zExtract", fileMapping, event, params2));
+ return MyCreateProcess(params2, 0, false, &event);
+}
+
+HRESULT ExtractArchives(const UStringVector &archivePaths,
+ const UString &outFolder, bool showDialog)
+{
+ UString params;
+ params = Get7zGuiPath();
+ params += L" x";
+ if (!outFolder.IsEmpty())
+ {
+ params += L" -o";
+ params += GetQuotedString(outFolder);
+ }
+ if (showDialog)
+ params += kShowDialogSwitch;
+ return ExtractGroupCommand(archivePaths, params);
+}
+
+HRESULT TestArchives(const UStringVector &archivePaths)
+{
+ UString params;
+ params = Get7zGuiPath();
+ params += L" t";
+ return ExtractGroupCommand(archivePaths, params);
+}
diff --git a/CPP/7zip/UI/Common/CompressCall.h b/CPP/7zip/UI/Common/CompressCall.h
new file mode 100755
index 00000000..95be95c3
--- /dev/null
+++ b/CPP/7zip/UI/Common/CompressCall.h
@@ -0,0 +1,28 @@
+// CompressCall.h
+
+#ifndef __COMPRESSCALL_H
+#define __COMPRESSCALL_H
+
+#include "Common/String.h"
+#include "Windows/Synchronization.h"
+
+HRESULT MyCreateProcess(const UString &params,
+ LPCWSTR lpCurrentDirectory, bool waitFinish,
+ NWindows::NSynchronization::CEvent *event);
+
+HRESULT CompressFiles(
+ const UString &curDir,
+ const UString &archiveName,
+ const UString &archiveType,
+ const UStringVector &names,
+ // const UString &outFolder,
+ bool email, bool showDialog, bool waitFinish);
+
+HRESULT ExtractArchives(
+ const UStringVector &archivePaths,
+ const UString &outFolder, bool showDialog);
+
+HRESULT TestArchives(const UStringVector &archivePaths);
+
+#endif
+
diff --git a/CPP/7zip/UI/Common/DefaultName.cpp b/CPP/7zip/UI/Common/DefaultName.cpp
new file mode 100755
index 00000000..8ee7c048
--- /dev/null
+++ b/CPP/7zip/UI/Common/DefaultName.cpp
@@ -0,0 +1,26 @@
+// DefaultName.cpp
+
+#include "StdAfx.h"
+
+#include "DefaultName.h"
+
+static const wchar_t *kEmptyFileAlias = L"[Content]";
+
+UString GetDefaultName2(const UString &fileName,
+ const UString &extension, const UString &addSubExtension)
+{
+ int extLength = extension.Length();
+ int fileNameLength = fileName.Length();
+ if (fileNameLength > extLength + 1)
+ {
+ int dotPos = fileNameLength - (extLength + 1);
+ if (fileName[dotPos] == '.')
+ if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0)
+ return fileName.Left(dotPos) + addSubExtension;
+ }
+ int dotPos = fileName.ReverseFind(L'.');
+ if (dotPos > 0)
+ return fileName.Left(dotPos) + addSubExtension;
+ return kEmptyFileAlias;
+}
+
diff --git a/CPP/7zip/UI/Common/DefaultName.h b/CPP/7zip/UI/Common/DefaultName.h
new file mode 100755
index 00000000..ff6330fa
--- /dev/null
+++ b/CPP/7zip/UI/Common/DefaultName.h
@@ -0,0 +1,11 @@
+// DefaultName.h
+
+#ifndef __DEFAULTNAME_H
+#define __DEFAULTNAME_H
+
+#include "Common/String.h"
+
+UString GetDefaultName2(const UString &fileName,
+ const UString &extension, const UString &addSubExtension);
+
+#endif
diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h
new file mode 100755
index 00000000..9537071c
--- /dev/null
+++ b/CPP/7zip/UI/Common/DirItem.h
@@ -0,0 +1,34 @@
+// DirItem.h
+
+#ifndef __DIR_ITEM_H
+#define __DIR_ITEM_H
+
+#include "Common/String.h"
+#include "Common/Types.h"
+
+struct CDirItem
+{
+ UInt32 Attributes;
+ FILETIME CreationTime;
+ FILETIME LastAccessTime;
+ FILETIME LastWriteTime;
+ UInt64 Size;
+ UString Name;
+ UString FullPath;
+ bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
+};
+
+struct CArchiveItem
+{
+ bool IsDirectory;
+ // DWORD Attributes;
+ // NWindows::NCOM::CPropVariant LastWriteTime;
+ FILETIME LastWriteTime;
+ bool SizeIsDefined;
+ UInt64 Size;
+ UString Name;
+ bool Censored;
+ int IndexInServer;
+};
+
+#endif
diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp
new file mode 100755
index 00000000..454092ec
--- /dev/null
+++ b/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -0,0 +1,281 @@
+// EnumDirItems.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/Wildcard.h"
+#include "Common/MyCom.h"
+
+#include "EnumDirItems.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NName;
+
+void AddDirFileInfo(
+ const UString &prefix, // prefix for logical path
+ const UString &fullPathName, // path on disk: can be relative to some basePrefix
+ const NFind::CFileInfoW &fileInfo,
+ CObjectVector<CDirItem> &dirItems)
+{
+ CDirItem item;
+ item.Attributes = fileInfo.Attributes;
+ item.Size = fileInfo.Size;
+ item.CreationTime = fileInfo.CreationTime;
+ item.LastAccessTime = fileInfo.LastAccessTime;
+ item.LastWriteTime = fileInfo.LastWriteTime;
+ item.Name = prefix + fileInfo.Name;
+ item.FullPath = fullPathName;
+ dirItems.Add(item);
+}
+
+static void EnumerateDirectory(
+ const UString &baseFolderPrefix, // base (disk) prefix for scanning
+ const UString &directory, // additional disk prefix starting from baseFolderPrefix
+ const UString &prefix, // logical prefix
+ CObjectVector<CDirItem> &dirItems,
+ UStringVector &errorPaths,
+ CRecordVector<DWORD> &errorCodes)
+{
+ NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard));
+ for (;;)
+ {
+ NFind::CFileInfoW fileInfo;
+ bool found;
+ if (!enumerator.Next(fileInfo, found))
+ {
+ errorCodes.Add(::GetLastError());
+ errorPaths.Add(baseFolderPrefix + directory);
+ return;
+ }
+ if (!found)
+ break;
+ AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo, dirItems);
+ if (fileInfo.IsDirectory())
+ {
+ EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter),
+ prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes);
+ }
+ }
+}
+
+void EnumerateDirItems(
+ const UString &baseFolderPrefix, // base (disk) prefix for scanning
+ const UStringVector &fileNames, // names relative to baseFolderPrefix
+ const UString &archiveNamePrefix,
+ CObjectVector<CDirItem> &dirItems,
+ UStringVector &errorPaths,
+ CRecordVector<DWORD> &errorCodes)
+{
+ for(int i = 0; i < fileNames.Size(); i++)
+ {
+ const UString &fileName = fileNames[i];
+ NFind::CFileInfoW fileInfo;
+ if (!NFind::FindFile(baseFolderPrefix + fileName, fileInfo))
+ {
+ errorCodes.Add(::GetLastError());
+ errorPaths.Add(baseFolderPrefix + fileName);
+ continue;
+ }
+ AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems);
+ if (fileInfo.IsDirectory())
+ {
+ EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter),
+ archiveNamePrefix + fileInfo.Name + wchar_t(kDirDelimiter),
+ dirItems, errorPaths, errorCodes);
+ }
+ }
+}
+
+static HRESULT EnumerateDirItems(
+ const NWildcard::CCensorNode &curNode,
+ const UString &diskPrefix, // full disk path prefix
+ const UString &archivePrefix, // prefix from root
+ const UStringVector &addArchivePrefix, // prefix from curNode
+ CObjectVector<CDirItem> &dirItems,
+ bool enterToSubFolders,
+ IEnumDirItemCallback *callback,
+ UStringVector &errorPaths,
+ CRecordVector<DWORD> &errorCodes)
+{
+ if (!enterToSubFolders)
+ if (curNode.NeedCheckSubDirs())
+ enterToSubFolders = true;
+ if (callback)
+ RINOK(callback->CheckBreak());
+
+ // try direct_names case at first
+ if (addArchivePrefix.IsEmpty() && !enterToSubFolders)
+ {
+ // check that all names are direct
+ int i;
+ for (i = 0; i < curNode.IncludeItems.Size(); i++)
+ {
+ const NWildcard::CItem &item = curNode.IncludeItems[i];
+ if (item.Recursive || item.PathParts.Size() != 1)
+ break;
+ const UString &name = item.PathParts.Front();
+ if (name.IsEmpty() || DoesNameContainWildCard(name))
+ break;
+ }
+ if (i == curNode.IncludeItems.Size())
+ {
+ // all names are direct (no wildcards)
+ // so we don't need file_system's dir enumerator
+ CRecordVector<bool> needEnterVector;
+ for (i = 0; i < curNode.IncludeItems.Size(); i++)
+ {
+ const NWildcard::CItem &item = curNode.IncludeItems[i];
+ const UString &name = item.PathParts.Front();
+ const UString fullPath = diskPrefix + name;
+ NFind::CFileInfoW fileInfo;
+ if (!NFind::FindFile(fullPath, fileInfo))
+ {
+ errorCodes.Add(::GetLastError());
+ errorPaths.Add(fullPath);
+ continue;
+ }
+ bool isDir = fileInfo.IsDirectory();
+ if (isDir && !item.ForDir || !isDir && !item.ForFile)
+ {
+ errorCodes.Add((DWORD)E_FAIL);
+ errorPaths.Add(fullPath);
+ continue;
+ }
+ const UString realName = fileInfo.Name;
+ const UString realDiskPath = diskPrefix + realName;
+ {
+ UStringVector pathParts;
+ pathParts.Add(fileInfo.Name);
+ if (curNode.CheckPathToRoot(false, pathParts, !isDir))
+ continue;
+ }
+ AddDirFileInfo(archivePrefix, realDiskPath, fileInfo, dirItems);
+ if (!isDir)
+ continue;
+
+ UStringVector addArchivePrefixNew;
+ const NWildcard::CCensorNode *nextNode = 0;
+ int index = curNode.FindSubNode(name);
+ if (index >= 0)
+ {
+ for (int t = needEnterVector.Size(); t <= index; t++)
+ needEnterVector.Add(true);
+ needEnterVector[index] = false;
+ nextNode = &curNode.SubNodes[index];
+ }
+ else
+ {
+ nextNode = &curNode;
+ addArchivePrefixNew.Add(name); // don't change it to realName. It's for shortnames support
+ }
+ RINOK(EnumerateDirItems(*nextNode,
+ realDiskPath + wchar_t(kDirDelimiter),
+ archivePrefix + realName + wchar_t(kDirDelimiter),
+ addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes));
+ }
+ for (i = 0; i < curNode.SubNodes.Size(); i++)
+ {
+ if (i < needEnterVector.Size())
+ if (!needEnterVector[i])
+ continue;
+ const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
+ const UString fullPath = diskPrefix + nextNode.Name;
+ NFind::CFileInfoW fileInfo;
+ if (!NFind::FindFile(fullPath, fileInfo))
+ {
+ if (!nextNode.AreThereIncludeItems())
+ continue;
+ errorCodes.Add(::GetLastError());
+ errorPaths.Add(fullPath);
+ continue;
+ }
+ if (!fileInfo.IsDirectory())
+ {
+ errorCodes.Add((DWORD)E_FAIL);
+ errorPaths.Add(fullPath);
+ continue;
+ }
+ RINOK(EnumerateDirItems(nextNode,
+ diskPrefix + fileInfo.Name + wchar_t(kDirDelimiter),
+ archivePrefix + fileInfo.Name + wchar_t(kDirDelimiter),
+ UStringVector(), dirItems, false, callback, errorPaths, errorCodes));
+ }
+ return S_OK;
+ }
+ }
+
+
+ NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard));
+ for (;;)
+ {
+ NFind::CFileInfoW fileInfo;
+ bool found;
+ if (!enumerator.Next(fileInfo, found))
+ {
+ errorCodes.Add(::GetLastError());
+ errorPaths.Add(diskPrefix);
+ break;
+ }
+ if (!found)
+ break;
+
+ if (callback)
+ RINOK(callback->CheckBreak());
+ const UString &name = fileInfo.Name;
+ bool enterToSubFolders2 = enterToSubFolders;
+ UStringVector addArchivePrefixNew = addArchivePrefix;
+ addArchivePrefixNew.Add(name);
+ {
+ UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);
+ if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fileInfo.IsDirectory()))
+ continue;
+ }
+ if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fileInfo.IsDirectory()))
+ {
+ AddDirFileInfo(archivePrefix, diskPrefix + name, fileInfo, dirItems);
+ if (fileInfo.IsDirectory())
+ enterToSubFolders2 = true;
+ }
+ if (!fileInfo.IsDirectory())
+ continue;
+
+ const NWildcard::CCensorNode *nextNode = 0;
+ if (addArchivePrefix.IsEmpty())
+ {
+ int index = curNode.FindSubNode(name);
+ if (index >= 0)
+ nextNode = &curNode.SubNodes[index];
+ }
+ if (!enterToSubFolders2 && nextNode == 0)
+ continue;
+
+ addArchivePrefixNew = addArchivePrefix;
+ if (nextNode == 0)
+ {
+ nextNode = &curNode;
+ addArchivePrefixNew.Add(name);
+ }
+ RINOK(EnumerateDirItems(*nextNode,
+ diskPrefix + name + wchar_t(kDirDelimiter),
+ archivePrefix + name + wchar_t(kDirDelimiter),
+ addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes));
+ }
+ return S_OK;
+}
+
+HRESULT EnumerateItems(
+ const NWildcard::CCensor &censor,
+ CObjectVector<CDirItem> &dirItems,
+ IEnumDirItemCallback *callback,
+ UStringVector &errorPaths,
+ CRecordVector<DWORD> &errorCodes)
+{
+ for (int i = 0; i < censor.Pairs.Size(); i++)
+ {
+ const NWildcard::CPair &pair = censor.Pairs[i];
+ RINOK(EnumerateDirItems(pair.Head, pair.Prefix, L"", UStringVector(), dirItems, false,
+ callback, errorPaths, errorCodes));
+ }
+ return S_OK;
+}
diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h
new file mode 100755
index 00000000..8d5495a8
--- /dev/null
+++ b/CPP/7zip/UI/Common/EnumDirItems.h
@@ -0,0 +1,39 @@
+// EnumDirItems.h
+
+#ifndef __ENUM_DIR_ITEMS_H
+#define __ENUM_DIR_ITEMS_H
+
+#include "Common/Wildcard.h"
+#include "DirItem.h"
+
+#include "Windows/FileFind.h"
+
+void AddDirFileInfo(
+ const UString &prefix,
+ const UString &fullPathName,
+ const NWindows::NFile::NFind::CFileInfoW &fileInfo,
+ CObjectVector<CDirItem> &dirItems);
+
+
+void EnumerateDirItems(
+ const UString &baseFolderPrefix,
+ const UStringVector &fileNames,
+ const UString &archiveNamePrefix,
+ CObjectVector<CDirItem> &dirItems,
+ UStringVector &errorPaths,
+ CRecordVector<DWORD> &errorCodes);
+
+struct IEnumDirItemCallback
+{
+ virtual HRESULT CheckBreak() { return S_OK; }
+};
+
+
+HRESULT EnumerateItems(
+ const NWildcard::CCensor &censor,
+ CObjectVector<CDirItem> &dirItems,
+ IEnumDirItemCallback *callback,
+ UStringVector &errorPaths,
+ CRecordVector<DWORD> &errorCodes);
+
+#endif
diff --git a/CPP/7zip/UI/Common/ExitCode.h b/CPP/7zip/UI/Common/ExitCode.h
new file mode 100755
index 00000000..0aac3695
--- /dev/null
+++ b/CPP/7zip/UI/Common/ExitCode.h
@@ -0,0 +1,27 @@
+// ExitCode.h
+
+#ifndef __EXIT_CODE_H
+#define __EXIT_CODE_H
+
+namespace NExitCode {
+
+enum EEnum {
+
+ kSuccess = 0, // Successful operation
+ kWarning = 1, // Non fatal error(s) occurred
+ kFatalError = 2, // A fatal error occurred
+ // kCRCError = 3, // A CRC error occurred when unpacking
+ // kLockedArchive = 4, // Attempt to modify an archive previously locked
+ // kWriteError = 5, // Write to disk error
+ // kOpenError = 6, // Open file error
+ kUserError = 7, // Command line option error
+ kMemoryError = 8, // Not enough memory for operation
+ // kCreateFileError = 9, // Create file error
+
+ kUserBreak = 255 // User stopped the process
+
+};
+
+}
+
+#endif
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
new file mode 100755
index 00000000..34fb383b
--- /dev/null
+++ b/CPP/7zip/UI/Common/Extract.cpp
@@ -0,0 +1,152 @@
+// Extract.cpp
+
+#include "StdAfx.h"
+
+#include "Extract.h"
+
+#include "Windows/Defs.h"
+#include "Windows/FileDir.h"
+
+#include "OpenArchive.h"
+#include "SetProperties.h"
+
+#ifndef EXCLUDE_COM
+#include "Windows/DLL.h"
+#endif
+
+using namespace NWindows;
+
+HRESULT DecompressArchive(
+ IInArchive *archive,
+ const UString &defaultName,
+ const NWildcard::CCensorNode &wildcardCensor,
+ const CExtractOptions &options,
+ IExtractCallbackUI *callback,
+ UString &errorMessage)
+{
+ CRecordVector<UInt32> realIndices;
+ UInt32 numItems;
+ RINOK(archive->GetNumberOfItems(&numItems));
+
+ for(UInt32 i = 0; i < numItems; i++)
+ {
+ UString filePath;
+ RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath));
+ bool isFolder;
+ RINOK(IsArchiveItemFolder(archive, i, isFolder));
+ if (!wildcardCensor.CheckPath(filePath, !isFolder))
+ continue;
+ realIndices.Add(i);
+ }
+ if (realIndices.Size() == 0)
+ {
+ callback->ThereAreNoFiles();
+ return S_OK;
+ }
+
+ CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
+
+ UStringVector removePathParts;
+
+ UString outDir = options.OutputDir;
+ outDir.Replace(L"*", defaultName);
+ if(!outDir.IsEmpty())
+ if(!NFile::NDirectory::CreateComplexDirectory(outDir))
+ {
+ HRESULT res = ::GetLastError();
+ if (res == S_OK)
+ res = E_FAIL;
+ errorMessage = ((UString)L"Can not create output directory ") + outDir;
+ return res;
+ }
+
+ extractCallbackSpec->Init(
+ archive,
+ callback,
+ options.StdOutMode,
+ outDir,
+ options.PathMode,
+ options.OverwriteMode,
+ removePathParts,
+ options.DefaultItemName,
+ options.ArchiveFileInfo.LastWriteTime,
+ options.ArchiveFileInfo.Attributes);
+
+ #ifdef COMPRESS_MT
+ RINOK(SetProperties(archive, options.Properties));
+ #endif
+
+ HRESULT result = archive->Extract(&realIndices.Front(),
+ realIndices.Size(), options.TestMode? 1: 0,
+ extractCallback);
+
+ return callback->ExtractResult(result);
+}
+
+HRESULT DecompressArchives(
+ UStringVector &archivePaths, UStringVector &archivePathsFull,
+ const NWildcard::CCensorNode &wildcardCensor,
+ const CExtractOptions &optionsSpec,
+ IOpenCallbackUI *openCallback,
+ IExtractCallbackUI *extractCallback,
+ UString &errorMessage)
+{
+ CExtractOptions options = optionsSpec;
+ for (int i = 0; i < archivePaths.Size(); i++)
+ {
+ const UString &archivePath = archivePaths[i];
+ NFile::NFind::CFileInfoW archiveFileInfo;
+ if (!NFile::NFind::FindFile(archivePath, archiveFileInfo))
+ throw "there is no such archive";
+
+ if (archiveFileInfo.IsDirectory())
+ throw "there is no such archive";
+
+ options.ArchiveFileInfo = archiveFileInfo;
+
+ #ifndef _NO_CRYPTO
+ openCallback->ClearPasswordWasAskedFlag();
+ #endif
+
+ RINOK(extractCallback->BeforeOpen(archivePath));
+ CArchiveLink archiveLink;
+ HRESULT result = MyOpenArchive(archivePath, archiveLink, openCallback);
+
+ bool crypted = false;
+ #ifndef _NO_CRYPTO
+ crypted = openCallback->WasPasswordAsked();
+ #endif
+
+ RINOK(extractCallback->OpenResult(archivePath, result, crypted));
+ if (result != S_OK)
+ continue;
+
+ for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
+ {
+ int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
+ if (index >= 0 && index > i)
+ {
+ archivePaths.Delete(index);
+ archivePathsFull.Delete(index);
+ }
+ }
+
+ #ifndef _NO_CRYPTO
+ UString password;
+ RINOK(openCallback->GetPasswordIfAny(password));
+ if (!password.IsEmpty())
+ {
+ RINOK(extractCallback->SetPassword(password));
+ }
+ #endif
+
+ options.DefaultItemName = archiveLink.GetDefaultItemName();
+ RINOK(DecompressArchive(
+ archiveLink.GetArchive(), archiveLink.GetDefaultItemName(),
+ wildcardCensor, options, extractCallback, errorMessage));
+ if (!errorMessage.IsEmpty())
+ return E_FAIL;
+ }
+ return S_OK;
+}
diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h
new file mode 100755
index 00000000..c7b47c84
--- /dev/null
+++ b/CPP/7zip/UI/Common/Extract.h
@@ -0,0 +1,59 @@
+// Extract.h
+
+#ifndef __EXTRACT_H
+#define __EXTRACT_H
+
+#include "Common/Wildcard.h"
+#include "Windows/FileFind.h"
+
+#include "../../Archive/IArchive.h"
+
+#include "ArchiveExtractCallback.h"
+#include "ArchiveOpenCallback.h"
+#include "ExtractMode.h"
+#include "Property.h"
+
+class CExtractOptions
+{
+public:
+ bool StdOutMode;
+ bool TestMode;
+ NExtract::NPathMode::EEnum PathMode;
+
+ UString OutputDir;
+ bool YesToAll;
+ UString DefaultItemName;
+ NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo;
+
+ // bool ShowDialog;
+ // bool PasswordEnabled;
+ // UString Password;
+ #ifdef COMPRESS_MT
+ CObjectVector<CProperty> Properties;
+ #endif
+
+ NExtract::NOverwriteMode::EEnum OverwriteMode;
+
+ CExtractOptions():
+ StdOutMode(false),
+ YesToAll(false),
+ TestMode(false),
+ PathMode(NExtract::NPathMode::kFullPathnames),
+ OverwriteMode(NExtract::NOverwriteMode::kAskBefore)
+ {}
+
+ /*
+ bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) ||
+ (ExtractMode == NExtractMode::kFullPath); }
+ */
+};
+
+HRESULT DecompressArchives(
+ UStringVector &archivePaths, UStringVector &archivePathsFull,
+ const NWildcard::CCensorNode &wildcardCensor,
+ const CExtractOptions &options,
+ IOpenCallbackUI *openCallback,
+ IExtractCallbackUI *extractCallback,
+ UString &errorMessage);
+
+#endif
diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h
new file mode 100755
index 00000000..96b5a8cd
--- /dev/null
+++ b/CPP/7zip/UI/Common/ExtractMode.h
@@ -0,0 +1,31 @@
+// ExtractMode.h
+
+#ifndef __EXTRACT_MODE_H
+#define __EXTRACT_MODE_H
+
+namespace NExtract {
+
+ namespace NPathMode
+ {
+ enum EEnum
+ {
+ kFullPathnames,
+ kCurrentPathnames,
+ kNoPathnames
+ };
+ }
+
+ namespace NOverwriteMode
+ {
+ enum EEnum
+ {
+ kAskBefore,
+ kWithoutPrompt,
+ kSkipExisting,
+ kAutoRename,
+ kAutoRenameExisting
+ };
+ }
+}
+
+#endif
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
new file mode 100755
index 00000000..a0b17282
--- /dev/null
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
@@ -0,0 +1,75 @@
+// ExtractingFilePath.cpp
+
+#include "StdAfx.h"
+#include "ExtractingFilePath.h"
+
+static void ReplaceDisk(UString &s)
+{
+ int i;
+ for (i = 0; i < s.Length(); i++)
+ if (s[i] != ' ')
+ break;
+ if (s.Length() > i + 1)
+ {
+ if (s[i + 1] == L':')
+ {
+ s.Delete(i + 1);
+ // s.Insert(i + 1, L'_');
+ }
+ }
+}
+
+UString GetCorrectFileName(const UString &path)
+{
+ UString result = path;
+ {
+ UString test = path;
+ test.Trim();
+ if (test == L"..")
+ result.Replace(L"..", L"");
+ }
+ ReplaceDisk(result);
+ return result;
+}
+
+UString GetCorrectPath(const UString &path)
+{
+ UString result = path;
+ int first;
+ for (first = 0; first < result.Length(); first++)
+ if (result[first] != ' ')
+ break;
+ while(result.Length() > first)
+ {
+ if (
+ #ifdef _WIN32
+ result[first] == L'\\' ||
+ #endif
+ result[first] == L'/')
+ {
+ result.Delete(first);
+ continue;
+ }
+ break;
+ }
+ #ifdef _WIN32
+ result.Replace(L"..\\", L"");
+ #endif
+ result.Replace(L"../", L"");
+
+ ReplaceDisk(result);
+ return result;
+}
+
+void MakeCorrectPath(UStringVector &pathParts)
+{
+ for (int i = 0; i < pathParts.Size();)
+ {
+ UString &s = pathParts[i];
+ s = GetCorrectFileName(s);
+ if (s.IsEmpty())
+ pathParts.Delete(i);
+ else
+ i++;
+ }
+}
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h
new file mode 100755
index 00000000..0ae9e9b8
--- /dev/null
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.h
@@ -0,0 +1,12 @@
+// ExtractingFilePath.h
+
+#ifndef __EXTRACTINGFILEPATH_H
+#define __EXTRACTINGFILEPATH_H
+
+#include "Common/String.h"
+
+UString GetCorrectFileName(const UString &path);
+UString GetCorrectPath(const UString &path);
+void MakeCorrectPath(UStringVector &pathParts);
+
+#endif
diff --git a/CPP/7zip/UI/Common/HandlerLoader.h b/CPP/7zip/UI/Common/HandlerLoader.h
new file mode 100755
index 00000000..2a878019
--- /dev/null
+++ b/CPP/7zip/UI/Common/HandlerLoader.h
@@ -0,0 +1,38 @@
+// HandlerLoader.h
+
+#ifndef __HANDLERLOADER_H
+#define __HANDLERLOADER_H
+
+#include "../../ICoder.h"
+#include "Windows/DLL.h"
+
+typedef UInt32 (WINAPI * CreateObjectFunc)(
+ const GUID *clsID,
+ const GUID *interfaceID,
+ void **outObject);
+
+class CHandlerLoader: public NWindows::NDLL::CLibrary
+{
+public:
+ HRESULT CreateHandler(LPCWSTR filepath, REFGUID clsID,
+ void **archive, bool outHandler)
+ {
+ if (!Load(filepath))
+ return GetLastError();
+ CreateObjectFunc createObject = (CreateObjectFunc)
+ GetProcAddress("CreateObject");
+ if (createObject == NULL)
+ {
+ HRESULT res = ::GetLastError();
+ Free();
+ return res;
+ }
+ HRESULT res = createObject(&clsID,
+ outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);
+ if (res != 0)
+ Free();
+ return res;
+ }
+};
+
+#endif
diff --git a/CPP/7zip/UI/Common/IFileExtractCallback.h b/CPP/7zip/UI/Common/IFileExtractCallback.h
new file mode 100755
index 00000000..c70d7021
--- /dev/null
+++ b/CPP/7zip/UI/Common/IFileExtractCallback.h
@@ -0,0 +1,46 @@
+// IFileExtractCallback.h
+
+#ifndef __IFILEEXTRACTCALLBACK_H
+#define __IFILEEXTRACTCALLBACK_H
+
+#include "Common/String.h"
+
+namespace NOverwriteAnswer
+{
+ enum EEnum
+ {
+ kYes,
+ kYesToAll,
+ kNo,
+ kNoToAll,
+ kAutoRename,
+ kCancel,
+ };
+}
+
+// {23170F69-40C1-278A-0000-000100070000}
+DEFINE_GUID(IID_IFolderArchiveExtractCallback,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000100070000")
+IFolderArchiveExtractCallback: public IProgress
+{
+public:
+ STDMETHOD(AskOverwrite)(
+ const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
+ const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
+ Int32 *answer) PURE;
+ STDMETHOD(PrepareOperation)(const wchar_t *name, Int32 askExtractMode, const UInt64 *position) PURE;
+ STDMETHOD(MessageError)(const wchar_t *message) PURE;
+ STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE;
+};
+
+struct IExtractCallbackUI: IFolderArchiveExtractCallback
+{
+ virtual HRESULT BeforeOpen(const wchar_t *name) = 0;
+ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0;
+ virtual HRESULT ThereAreNoFiles() = 0;
+ virtual HRESULT ExtractResult(HRESULT result) = 0;
+ virtual HRESULT SetPassword(const UString &password) = 0;
+};
+
+#endif
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
new file mode 100755
index 00000000..ce1a6de3
--- /dev/null
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -0,0 +1,531 @@
+// OpenArchive.cpp
+
+#include "StdAfx.h"
+
+#include "OpenArchive.h"
+
+#include "Common/Wildcard.h"
+
+#include "Windows/FileName.h"
+#include "Windows/FileDir.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/StreamUtils.h"
+
+#include "Common/StringConvert.h"
+
+#ifdef FORMAT_7Z
+#include "../../Archive/7z/7zHandler.h"
+#endif
+
+#ifdef FORMAT_BZIP2
+#include "../../Archive/BZip2/BZip2Handler.h"
+#endif
+
+#ifdef FORMAT_CAB
+#include "../../Archive/Cab/CabHandler.h"
+#endif
+
+#ifdef FORMAT_GZIP
+#include "../../Archive/GZip/GZipHandler.h"
+#endif
+
+#ifdef FORMAT_SPLIT
+#include "../../Archive/Split/SplitHandler.h"
+#endif
+
+#ifdef FORMAT_TAR
+#include "../../Archive/Tar/TarHandler.h"
+#endif
+
+#ifdef FORMAT_ZIP
+#include "../../Archive/Zip/ZipHandler.h"
+#endif
+
+#ifdef FORMAT_Z
+#include "../../Archive/Z/ZHandler.h"
+#endif
+
+#ifndef EXCLUDE_COM
+#include "HandlerLoader.h"
+#endif
+
+#include "DefaultName.h"
+
+using namespace NWindows;
+
+HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result)
+{
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidPath, &prop));
+ if(prop.vt == VT_BSTR)
+ result = prop.bstrVal;
+ else if (prop.vt == VT_EMPTY)
+ result.Empty();
+ else
+ return E_FAIL;
+ return S_OK;
+}
+
+HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result)
+{
+ RINOK(GetArchiveItemPath(archive, index, result));
+ if (result.IsEmpty())
+ result = defaultName;
+ return S_OK;
+}
+
+HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index,
+ const FILETIME &defaultFileTime, FILETIME &fileTime)
+{
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidLastWriteTime, &prop));
+ if (prop.vt == VT_FILETIME)
+ fileTime = prop.filetime;
+ else if (prop.vt == VT_EMPTY)
+ fileTime = defaultFileTime;
+ else
+ return E_FAIL;
+ return S_OK;
+}
+
+static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
+{
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, propID, &prop));
+ if(prop.vt == VT_BOOL)
+ result = VARIANT_BOOLToBool(prop.boolVal);
+ else if (prop.vt == VT_EMPTY)
+ result = false;
+ else
+ return E_FAIL;
+ return S_OK;
+}
+
+HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
+{
+ return IsArchiveItemProp(archive, index, kpidIsFolder, result);
+}
+
+HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result)
+{
+ return IsArchiveItemProp(archive, index, kpidIsAnti, result);
+}
+
+// Static-SFX (for Linux) can be big.
+const UInt64 kMaxCheckStartPosition = 1 << 22;
+
+HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName)
+{
+ CInFileStream *inStreamSpec = new CInFileStream;
+ CMyComPtr<IInStream> inStream(inStreamSpec);
+ inStreamSpec->Open(fileName);
+ return archive->Open(inStream, &kMaxCheckStartPosition, NULL);
+}
+
+#ifndef _SFX
+static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
+{
+ for (size_t i = 0; i < size; i++)
+ if (p1[i] != p2[i])
+ return false;
+ return true;
+}
+#endif
+
+HRESULT OpenArchive(
+ IInStream *inStream,
+ const UString &fileName,
+ #ifndef EXCLUDE_COM
+ HMODULE *module,
+ #endif
+ IInArchive **archiveResult,
+ CArchiverInfo &archiverInfoResult,
+ UString &defaultItemName,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ *archiveResult = NULL;
+ CObjectVector<CArchiverInfo> archiverInfoList;
+ ReadArchiverInfoList(archiverInfoList);
+ UString extension;
+ {
+ int dotPos = fileName.ReverseFind(L'.');
+ if (dotPos >= 0)
+ extension = fileName.Mid(dotPos + 1);
+ }
+ CIntVector orderIndices;
+ int i;
+ bool finded = false;
+ for(i = 0; i < archiverInfoList.Size(); i++)
+ {
+ if (archiverInfoList[i].FindExtension(extension) >= 0)
+ {
+ orderIndices.Insert(0, i);
+ finded = true;
+ }
+ else
+ orderIndices.Add(i);
+ }
+
+ #ifndef _SFX
+ if (!finded)
+ {
+ CByteBuffer byteBuffer;
+ const UInt32 kBufferSize = (200 << 10);
+ byteBuffer.SetCapacity(kBufferSize);
+ Byte *buffer = byteBuffer;
+ RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+ UInt32 processedSize;
+ RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize));
+ int numFinded = 0;
+ for (int pos = (int)processedSize; pos >= 0 ; pos--)
+ {
+ for(int i = numFinded; i < orderIndices.Size(); i++)
+ {
+ int index = orderIndices[i];
+ const CArchiverInfo &ai = archiverInfoList[index];
+ const CByteBuffer &sig = ai.StartSignature;
+ if (sig.GetCapacity() == 0)
+ continue;
+ if (pos + sig.GetCapacity() > processedSize)
+ continue;
+ if (TestSignature(buffer + pos, sig, sig.GetCapacity()))
+ {
+ orderIndices.Delete(i);
+ orderIndices.Insert(0, index);
+ numFinded++;
+ }
+ }
+ }
+ }
+ #endif
+
+ HRESULT badResult = S_OK;
+ for(i = 0; i < orderIndices.Size(); i++)
+ {
+ inStream->Seek(0, STREAM_SEEK_SET, NULL);
+ const CArchiverInfo &archiverInfo = archiverInfoList[orderIndices[i]];
+ #ifndef EXCLUDE_COM
+ CHandlerLoader loader;
+ #endif
+ CMyComPtr<IInArchive> archive;
+
+ #ifdef FORMAT_7Z
+ if (archiverInfo.Name.CompareNoCase(L"7z") == 0)
+ archive = new NArchive::N7z::CHandler;
+ #endif
+
+ #ifdef FORMAT_BZIP2
+ if (archiverInfo.Name.CompareNoCase(L"BZip2") == 0)
+ archive = new NArchive::NBZip2::CHandler;
+ #endif
+
+ #ifdef FORMAT_CAB
+ if (archiverInfo.Name.CompareNoCase(L"Cab") == 0)
+ archive = new NArchive::NCab::CHandler;
+ #endif
+
+ #ifdef FORMAT_GZIP
+ if (archiverInfo.Name.CompareNoCase(L"GZip") == 0)
+ archive = new NArchive::NGZip::CHandler;
+ #endif
+
+ #ifdef FORMAT_SPLIT
+ if (archiverInfo.Name.CompareNoCase(L"Split") == 0)
+ archive = new NArchive::NSplit::CHandler;
+ #endif
+
+ #ifdef FORMAT_TAR
+ if (archiverInfo.Name.CompareNoCase(L"Tar") == 0)
+ archive = new NArchive::NTar::CHandler;
+ #endif
+
+ #ifdef FORMAT_ZIP
+ if (archiverInfo.Name.CompareNoCase(L"Zip") == 0)
+ archive = new NArchive::NZip::CHandler;
+ #endif
+
+ #ifdef FORMAT_Z
+ if (archiverInfo.Name.CompareNoCase(L"Z") == 0)
+ archive = new NArchive::NZ::CHandler;
+ #endif
+
+
+ #ifndef EXCLUDE_COM
+ if (!archive)
+ {
+ HRESULT result = loader.CreateHandler(archiverInfo.FilePath,
+ archiverInfo.ClassID, (void **)&archive, false);
+ if (result != S_OK)
+ continue;
+ }
+ #endif
+
+ if (!archive)
+ return E_FAIL;
+
+ HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback);
+ if(result == S_FALSE)
+ continue;
+ if(result != S_OK)
+ {
+ badResult = result;
+ if(result == E_ABORT)
+ break;
+ continue;
+ }
+ *archiveResult = archive.Detach();
+ #ifndef EXCLUDE_COM
+ *module = loader.Detach();
+ #endif
+ archiverInfoResult = archiverInfo;
+ int subExtIndex = archiverInfo.FindExtension(extension);
+ if (subExtIndex < 0)
+ subExtIndex = 0;
+ defaultItemName = GetDefaultName2(fileName,
+ archiverInfo.Extensions[subExtIndex].Ext,
+ archiverInfo.Extensions[subExtIndex].AddExt);
+
+ return S_OK;
+ }
+ if (badResult != S_OK)
+ return badResult;
+ return S_FALSE;
+}
+
+HRESULT OpenArchive(const UString &filePath,
+ #ifndef EXCLUDE_COM
+ HMODULE *module,
+ #endif
+ IInArchive **archiveResult,
+ CArchiverInfo &archiverInfo,
+ UString &defaultItemName,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ CInFileStream *inStreamSpec = new CInFileStream;
+ CMyComPtr<IInStream> inStream(inStreamSpec);
+ if (!inStreamSpec->Open(filePath))
+ return GetLastError();
+ return OpenArchive(inStream, ExtractFileNameFromPath(filePath),
+ #ifndef EXCLUDE_COM
+ module,
+ #endif
+ archiveResult, archiverInfo,
+ defaultItemName, openArchiveCallback);
+}
+
+static void MakeDefaultName(UString &name)
+{
+ int dotPos = name.ReverseFind(L'.');
+ if (dotPos < 0)
+ return;
+ UString ext = name.Mid(dotPos + 1);
+ if (ext.IsEmpty())
+ return;
+ for (int pos = 0; pos < ext.Length(); pos++)
+ if (ext[pos] < L'0' || ext[pos] > L'9')
+ return;
+ name = name.Left(dotPos);
+}
+
+HRESULT OpenArchive(const UString &fileName,
+ #ifndef EXCLUDE_COM
+ HMODULE *module0,
+ HMODULE *module1,
+ #endif
+ IInArchive **archive0,
+ IInArchive **archive1,
+ CArchiverInfo &archiverInfo0,
+ CArchiverInfo &archiverInfo1,
+ UString &defaultItemName0,
+ UString &defaultItemName1,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ HRESULT result = OpenArchive(fileName,
+ #ifndef EXCLUDE_COM
+ module0,
+ #endif
+ archive0, archiverInfo0, defaultItemName0, openArchiveCallback);
+ RINOK(result);
+ CMyComPtr<IInArchiveGetStream> getStream;
+ result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream);
+ if (result != S_OK || getStream == 0)
+ return S_OK;
+
+ CMyComPtr<ISequentialInStream> subSeqStream;
+ result = getStream->GetStream(0, &subSeqStream);
+ if (result != S_OK)
+ return S_OK;
+
+ CMyComPtr<IInStream> subStream;
+ if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK)
+ return S_OK;
+ if (!subStream)
+ return S_OK;
+
+ UInt32 numItems;
+ RINOK((*archive0)->GetNumberOfItems(&numItems));
+ if (numItems < 1)
+ return S_OK;
+
+ UString subPath;
+ RINOK(GetArchiveItemPath(*archive0, 0, subPath))
+ if (subPath.IsEmpty())
+ {
+ MakeDefaultName(defaultItemName0);
+ subPath = defaultItemName0;
+ if (archiverInfo0.Name.CompareNoCase(L"7z") == 0)
+ {
+ if (subPath.Right(3).CompareNoCase(L".7z") != 0)
+ subPath += L".7z";
+ }
+ }
+ else
+ subPath = ExtractFileNameFromPath(subPath);
+
+ CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
+ openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
+ if (setSubArchiveName)
+ setSubArchiveName->SetSubArchiveName(subPath);
+
+ result = OpenArchive(subStream, subPath,
+ #ifndef EXCLUDE_COM
+ module1,
+ #endif
+ archive1, archiverInfo1, defaultItemName1, openArchiveCallback);
+ return S_OK;
+}
+
+HRESULT MyOpenArchive(const UString &archiveName,
+ #ifndef EXCLUDE_COM
+ HMODULE *module,
+ #endif
+ IInArchive **archive,
+ UString &defaultItemName,
+ IOpenCallbackUI *openCallbackUI)
+{
+ COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
+ CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec;
+ openCallbackSpec->Callback = openCallbackUI;
+
+ UString fullName;
+ int fileNamePartStartIndex;
+ NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex);
+ openCallbackSpec->Init(
+ fullName.Left(fileNamePartStartIndex),
+ fullName.Mid(fileNamePartStartIndex));
+
+ CArchiverInfo archiverInfo;
+ return OpenArchive(archiveName,
+ #ifndef EXCLUDE_COM
+ module,
+ #endif
+ archive,
+ archiverInfo,
+ defaultItemName,
+ openCallback);
+}
+
+HRESULT MyOpenArchive(const UString &archiveName,
+ #ifndef EXCLUDE_COM
+ HMODULE *module0,
+ HMODULE *module1,
+ #endif
+ IInArchive **archive0,
+ IInArchive **archive1,
+ UString &defaultItemName0,
+ UString &defaultItemName1,
+ UStringVector &volumePaths,
+ IOpenCallbackUI *openCallbackUI)
+{
+ COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
+ CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec;
+ openCallbackSpec->Callback = openCallbackUI;
+
+ UString fullName;
+ int fileNamePartStartIndex;
+ NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex);
+ UString prefix = fullName.Left(fileNamePartStartIndex);
+ UString name = fullName.Mid(fileNamePartStartIndex);
+ openCallbackSpec->Init(prefix, name);
+
+ CArchiverInfo archiverInfo0, archiverInfo1;
+ HRESULT result = OpenArchive(archiveName,
+ #ifndef EXCLUDE_COM
+ module0,
+ module1,
+ #endif
+ archive0,
+ archive1,
+ archiverInfo0,
+ archiverInfo1,
+ defaultItemName0,
+ defaultItemName1,
+ openCallback);
+ RINOK(result);
+ volumePaths.Add(prefix + name);
+ for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++)
+ volumePaths.Add(prefix + openCallbackSpec->FileNames[i]);
+ return S_OK;
+}
+
+HRESULT CArchiveLink::Close()
+{
+ if (Archive1 != 0)
+ RINOK(Archive1->Close());
+ if (Archive0 != 0)
+ RINOK(Archive0->Close());
+ return S_OK;
+}
+
+void CArchiveLink::Release()
+{
+ if (Archive1 != 0)
+ Archive1.Release();
+ if (Archive0 != 0)
+ Archive0.Release();
+ #ifndef EXCLUDE_COM
+ Library1.Free();
+ Library0.Free();
+ #endif
+}
+
+HRESULT OpenArchive(const UString &archiveName,
+ CArchiveLink &archiveLink,
+ IArchiveOpenCallback *openCallback)
+{
+ return OpenArchive(archiveName,
+ #ifndef EXCLUDE_COM
+ &archiveLink.Library0, &archiveLink.Library1,
+ #endif
+ &archiveLink.Archive0, &archiveLink.Archive1,
+ archiveLink.ArchiverInfo0, archiveLink.ArchiverInfo1,
+ archiveLink.DefaultItemName0, archiveLink.DefaultItemName1,
+ openCallback);
+}
+
+HRESULT MyOpenArchive(const UString &archiveName,
+ CArchiveLink &archiveLink,
+ IOpenCallbackUI *openCallbackUI)
+{
+ return MyOpenArchive(archiveName,
+ #ifndef EXCLUDE_COM
+ &archiveLink.Library0, &archiveLink.Library1,
+ #endif
+ &archiveLink.Archive0, &archiveLink.Archive1,
+ archiveLink.DefaultItemName0, archiveLink.DefaultItemName1,
+ archiveLink.VolumePaths,
+ openCallbackUI);
+}
+
+HRESULT ReOpenArchive(CArchiveLink &archiveLink,
+ const UString &fileName)
+{
+ if (archiveLink.GetNumLevels() > 1)
+ return E_NOTIMPL;
+ if (archiveLink.GetNumLevels() == 0)
+ return MyOpenArchive(fileName, archiveLink, 0);
+ return ReOpenArchive(archiveLink.GetArchive(), fileName);
+}
diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h
new file mode 100755
index 00000000..f96b1ebf
--- /dev/null
+++ b/CPP/7zip/UI/Common/OpenArchive.h
@@ -0,0 +1,134 @@
+// OpenArchive.h
+
+#ifndef __OPENARCHIVE_H
+#define __OPENARCHIVE_H
+
+#include "Common/String.h"
+#include "Windows/FileFind.h"
+
+#include "../../Archive/IArchive.h"
+#include "ArchiverInfo.h"
+#include "ArchiveOpenCallback.h"
+
+#ifndef EXCLUDE_COM
+#include "Windows/DLL.h"
+#endif
+
+HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result);
+HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result);
+HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index,
+ const FILETIME &defaultFileTime, FILETIME &fileTime);
+HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result);
+HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result);
+
+struct ISetSubArchiveName
+{
+ virtual void SetSubArchiveName(const wchar_t *name) = 0;
+};
+
+HRESULT OpenArchive(
+ IInStream *inStream,
+ const UString &fileName,
+ #ifndef EXCLUDE_COM
+ HMODULE *module,
+ #endif
+ IInArchive **archiveResult,
+ CArchiverInfo &archiverInfoResult,
+ UString &defaultItemName,
+ IArchiveOpenCallback *openArchiveCallback);
+
+HRESULT OpenArchive(const UString &filePath,
+ #ifndef EXCLUDE_COM
+ HMODULE *module,
+ #endif
+ IInArchive **archive,
+ CArchiverInfo &archiverInfo,
+ UString &defaultItemName,
+ IArchiveOpenCallback *openArchiveCallback);
+
+HRESULT OpenArchive(const UString &filePath,
+ #ifndef EXCLUDE_COM
+ HMODULE *module0,
+ HMODULE *module1,
+ #endif
+ IInArchive **archive0,
+ IInArchive **archive1,
+ CArchiverInfo &archiverInfo0,
+ CArchiverInfo &archiverInfo1,
+ UString &defaultItemName0,
+ UString &defaultItemName1,
+ IArchiveOpenCallback *openArchiveCallback);
+
+
+HRESULT ReOpenArchive(IInArchive *archive,
+ const UString &fileName);
+
+HRESULT MyOpenArchive(const UString &archiveName,
+ #ifndef EXCLUDE_COM
+ HMODULE *module,
+ #endif
+ IInArchive **archive,
+ UString &defaultItemName,
+ IOpenCallbackUI *openCallbackUI);
+
+HRESULT MyOpenArchive(const UString &archiveName,
+ #ifndef EXCLUDE_COM
+ HMODULE *module0,
+ HMODULE *module1,
+ #endif
+ IInArchive **archive0,
+ IInArchive **archive1,
+ UString &defaultItemName0,
+ UString &defaultItemName1,
+ UStringVector &volumePaths,
+ IOpenCallbackUI *openCallbackUI);
+
+struct CArchiveLink
+{
+ #ifndef EXCLUDE_COM
+ NWindows::NDLL::CLibrary Library0;
+ NWindows::NDLL::CLibrary Library1;
+ #endif
+ CMyComPtr<IInArchive> Archive0;
+ CMyComPtr<IInArchive> Archive1;
+ UString DefaultItemName0;
+ UString DefaultItemName1;
+
+ CArchiverInfo ArchiverInfo0;
+ CArchiverInfo ArchiverInfo1;
+
+ UStringVector VolumePaths;
+
+ int GetNumLevels() const
+ {
+ int result = 0;
+ if (Archive0)
+ {
+ result++;
+ if (Archive1)
+ result++;
+ }
+ return result;
+ }
+
+
+ IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; }
+ UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; }
+ const CArchiverInfo &GetArchiverInfo() { return Archive1 != 0 ? ArchiverInfo1: ArchiverInfo0; }
+ HRESULT Close();
+ void Release();
+};
+
+HRESULT OpenArchive(const UString &archiveName,
+ CArchiveLink &archiveLink,
+ IArchiveOpenCallback *openCallback);
+
+HRESULT MyOpenArchive(const UString &archiveName,
+ CArchiveLink &archiveLink,
+ IOpenCallbackUI *openCallbackUI);
+
+HRESULT ReOpenArchive(CArchiveLink &archiveLink,
+ const UString &fileName);
+
+#endif
+
diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
new file mode 100755
index 00000000..8869e565
--- /dev/null
+++ b/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -0,0 +1,90 @@
+// PropIDUtils.cpp
+
+#include "StdAfx.h"
+
+#include "PropIDUtils.h"
+
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/FileFind.h"
+#include "Windows/PropVariantConversions.h"
+
+#include "../../PropID.h"
+
+using namespace NWindows;
+
+static UString ConvertUInt32ToString(UInt32 value)
+{
+ wchar_t buffer[32];
+ ConvertUInt64ToString(value, buffer);
+ return buffer;
+}
+
+static void ConvertUInt32ToHex(UInt32 value, wchar_t *s)
+{
+ for (int i = 0; i < 8; i++)
+ {
+ int t = value & 0xF;
+ value >>= 4;
+ s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10)));
+ }
+ s[8] = L'\0';
+}
+
+UString ConvertPropertyToString(const PROPVARIANT &propVariant,
+ PROPID propID, bool full)
+{
+ switch(propID)
+ {
+ case kpidCreationTime:
+ case kpidLastWriteTime:
+ case kpidLastAccessTime:
+ {
+ if (propVariant.vt != VT_FILETIME)
+ return UString(); // It is error;
+ FILETIME localFileTime;
+ if (propVariant.filetime.dwHighDateTime == 0 &&
+ propVariant.filetime.dwLowDateTime == 0)
+ return UString();
+ if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime))
+ return UString(); // It is error;
+ return ConvertFileTimeToString(localFileTime, true, full);
+ }
+ case kpidCRC:
+ {
+ if(propVariant.vt != VT_UI4)
+ break;
+ wchar_t temp[12];
+ ConvertUInt32ToHex(propVariant.ulVal, temp);
+ return temp;
+ }
+ case kpidAttributes:
+ {
+ if(propVariant.vt != VT_UI4)
+ break;
+ UString result;
+ UInt32 attributes = propVariant.ulVal;
+ if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R';
+ if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H';
+ if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S';
+ if (NFile::NFind::NAttributes::IsDirectory(attributes)) result += L'D';
+ if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A';
+ if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C';
+ if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E';
+ return result;
+ }
+ case kpidDictionarySize:
+ {
+ if(propVariant.vt != VT_UI4)
+ break;
+ UInt32 size = propVariant.ulVal;
+ if (size % (1 << 20) == 0)
+ return ConvertUInt32ToString(size >> 20) + L"MB";
+ if (size % (1 << 10) == 0)
+ return ConvertUInt32ToString(size >> 10) + L"KB";
+ return ConvertUInt32ToString(size);
+ }
+ }
+ return ConvertPropVariantToString(propVariant);
+}
diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h
new file mode 100755
index 00000000..aa540885
--- /dev/null
+++ b/CPP/7zip/UI/Common/PropIDUtils.h
@@ -0,0 +1,11 @@
+// PropIDUtils.h
+
+#ifndef __PROPIDUTILS_H
+#define __PROPIDUTILS_H
+
+#include "Common/String.h"
+
+UString ConvertPropertyToString(const PROPVARIANT &aPropVariant,
+ PROPID aPropID, bool aFull = true);
+
+#endif
diff --git a/CPP/7zip/UI/Common/Property.h b/CPP/7zip/UI/Common/Property.h
new file mode 100755
index 00000000..57e7b452
--- /dev/null
+++ b/CPP/7zip/UI/Common/Property.h
@@ -0,0 +1,14 @@
+// Property.h
+
+#ifndef __PROPERTY_H
+#define __PROPERTY_H
+
+#include "Common/String.h"
+
+struct CProperty
+{
+ UString Name;
+ UString Value;
+};
+
+#endif
diff --git a/CPP/7zip/UI/Common/SetProperties.cpp b/CPP/7zip/UI/Common/SetProperties.cpp
new file mode 100755
index 00000000..6c92a847
--- /dev/null
+++ b/CPP/7zip/UI/Common/SetProperties.cpp
@@ -0,0 +1,65 @@
+// SetProperties.cpp
+
+#include "StdAfx.h"
+
+#include "SetProperties.h"
+
+#include "Windows/PropVariant.h"
+#include "Common/String.h"
+#include "Common/StringToInt.h"
+#include "Common/MyCom.h"
+
+#include "../../Archive/IArchive.h"
+
+using namespace NWindows;
+using namespace NCOM;
+
+static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
+{
+ const wchar_t *endPtr;
+ UInt64 result = ConvertStringToUInt64(s, &endPtr);
+ if (endPtr - (const wchar_t *)s != s.Length())
+ prop = s;
+ else if (result <= 0xFFFFFFFF)
+ prop = (UInt32)result;
+ else
+ prop = result;
+}
+
+HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties)
+{
+ if (properties.IsEmpty())
+ return S_OK;
+ CMyComPtr<ISetProperties> setProperties;
+ unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties);
+ if (!setProperties)
+ return S_OK;
+
+ UStringVector realNames;
+ CPropVariant *values = new CPropVariant[properties.Size()];
+ try
+ {
+ int i;
+ for(i = 0; i < properties.Size(); i++)
+ {
+ const CProperty &property = properties[i];
+ NCOM::CPropVariant propVariant;
+ if (!property.Value.IsEmpty())
+ ParseNumberString(property.Value, propVariant);
+ realNames.Add(property.Name);
+ values[i] = propVariant;
+ }
+ CRecordVector<const wchar_t *> names;
+ for(i = 0; i < realNames.Size(); i++)
+ names.Add((const wchar_t *)realNames[i]);
+
+ RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));
+ }
+ catch(...)
+ {
+ delete []values;
+ throw;
+ }
+ delete []values;
+ return S_OK;
+}
diff --git a/CPP/7zip/UI/Common/SetProperties.h b/CPP/7zip/UI/Common/SetProperties.h
new file mode 100755
index 00000000..892f1a21
--- /dev/null
+++ b/CPP/7zip/UI/Common/SetProperties.h
@@ -0,0 +1,10 @@
+// SetProperties.h
+
+#ifndef __SETPROPERTIES_H
+#define __SETPROPERTIES_H
+
+#include "Property.h"
+
+HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties);
+
+#endif
diff --git a/CPP/7zip/UI/Common/SortUtils.cpp b/CPP/7zip/UI/Common/SortUtils.cpp
new file mode 100755
index 00000000..c0111581
--- /dev/null
+++ b/CPP/7zip/UI/Common/SortUtils.cpp
@@ -0,0 +1,78 @@
+// SortUtils.cpp
+
+#include "StdAfx.h"
+
+#include "SortUtils.h"
+#include "Common/Types.h"
+
+/*
+template <class T>
+void TSortRefDown(T *p, UInt32 k, UInt32 size, int (*compare)(const T*, const T*, void *), void *param)
+{
+ T temp = p[k];
+ for (;;)
+ {
+ UInt32 s = (k << 1);
+ if (s > size)
+ break;
+ if (s < size && compare(p + s + 1, p + s, param) > 0)
+ s++;
+ if (compare(&temp, p + s, param) >= 0)
+ break;
+ p[k] = p[s];
+ k = s;
+ }
+ p[k] = temp;
+}
+
+template <class T>
+void TSort(T* p, UInt32 size, int (*compare)(const T*, const T*, void *), void *param)
+{
+ if (size <= 1)
+ return;
+ p--;
+ {
+ UInt32 i = size / 2;
+ do
+ TSortRefDown(p, i, size, compare, param);
+ while(--i != 0);
+ }
+ do
+ {
+ T temp = p[size];
+ p[size--] = p[1];
+ p[1] = temp;
+ TSortRefDown(p, 1, size, compare, param);
+ }
+ while (size > 1);
+}
+*/
+
+static int CompareStrings(const int *p1, const int *p2, void *param)
+{
+ const UStringVector &strings = *(const UStringVector *)param;
+ const UString &s1 = strings[*p1];
+ const UString &s2 = strings[*p2];
+ return s1.CompareNoCase(s2);
+}
+
+void SortStringsToIndices(const UStringVector &strings, CIntVector &indices)
+{
+ indices.Clear();
+ int numItems = strings.Size();
+ indices.Reserve(numItems);
+ for(int i = 0; i < numItems; i++)
+ indices.Add(i);
+ indices.Sort(CompareStrings, (void *)&strings);
+ // TSort(&indices.Front(), indices.Size(), CompareStrings, (void *)&strings);
+}
+
+void SortStrings(const UStringVector &src, UStringVector &dest)
+{
+ CIntVector indices;
+ SortStringsToIndices(src, indices);
+ dest.Clear();
+ dest.Reserve(indices.Size());
+ for (int i = 0; i < indices.Size(); i++)
+ dest.Add(src[indices[i]]);
+}
diff --git a/CPP/7zip/UI/Common/SortUtils.h b/CPP/7zip/UI/Common/SortUtils.h
new file mode 100755
index 00000000..5b9af264
--- /dev/null
+++ b/CPP/7zip/UI/Common/SortUtils.h
@@ -0,0 +1,11 @@
+// SortUtils.h
+
+#ifndef __SORTUTLS_H
+#define __SORTUTLS_H
+
+#include "Common/String.h"
+
+void SortStringsToIndices(const UStringVector &strings, CIntVector &indices);
+void SortStrings(const UStringVector &src, UStringVector &dest);
+
+#endif
diff --git a/CPP/7zip/UI/Common/StdAfx.h b/CPP/7zip/UI/Common/StdAfx.h
new file mode 100755
index 00000000..100f4344
--- /dev/null
+++ b/CPP/7zip/UI/Common/StdAfx.h
@@ -0,0 +1,9 @@
+// stdafx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif
diff --git a/CPP/7zip/UI/Common/TempFiles.cpp b/CPP/7zip/UI/Common/TempFiles.cpp
new file mode 100755
index 00000000..3e604aea
--- /dev/null
+++ b/CPP/7zip/UI/Common/TempFiles.cpp
@@ -0,0 +1,22 @@
+// TempFiles.cpp
+
+#include "StdAfx.h"
+
+#include "TempFiles.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/FileIO.h"
+
+using namespace NWindows;
+using namespace NFile;
+
+void CTempFiles::Clear()
+{
+ while(!Paths.IsEmpty())
+ {
+ NDirectory::DeleteFileAlways(Paths.Back());
+ Paths.DeleteBack();
+ }
+}
+
+
diff --git a/CPP/7zip/UI/Common/TempFiles.h b/CPP/7zip/UI/Common/TempFiles.h
new file mode 100755
index 00000000..173713a0
--- /dev/null
+++ b/CPP/7zip/UI/Common/TempFiles.h
@@ -0,0 +1,16 @@
+// TempFiles.h
+
+#ifndef __TEMPFILES_H
+#define __TEMPFILES_H
+
+#include "Common/String.h"
+
+class CTempFiles
+{
+ void Clear();
+public:
+ UStringVector Paths;
+ ~CTempFiles() { Clear(); }
+};
+
+#endif
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
new file mode 100755
index 00000000..cd7975d0
--- /dev/null
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -0,0 +1,818 @@
+// Update.cpp
+
+#include "StdAfx.h"
+
+#ifdef _WIN32
+#include <mapi.h>
+#endif
+
+#include "Update.h"
+
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+#include "Common/CommandLineParser.h"
+
+#ifdef _WIN32
+#include "Windows/DLL.h"
+#endif
+
+#include "Windows/Defs.h"
+#include "Windows/FileDir.h"
+#include "Windows/FileFind.h"
+#include "Windows/FileName.h"
+#include "Windows/PropVariant.h"
+#include "Windows/PropVariantConversions.h"
+// #include "Windows/Synchronization.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Compress/Copy/CopyCoder.h"
+
+#include "../Common/DirItem.h"
+#include "../Common/EnumDirItems.h"
+#include "../Common/UpdateProduce.h"
+#include "../Common/OpenArchive.h"
+
+#include "TempFiles.h"
+#include "UpdateCallback.h"
+#include "EnumDirItems.h"
+#include "SetProperties.h"
+
+#ifdef FORMAT_7Z
+#include "../../Archive/7z/7zHandler.h"
+#endif
+
+#ifdef FORMAT_BZIP2
+#include "../../Archive/BZip2/BZip2Handler.h"
+#endif
+
+#ifdef FORMAT_GZIP
+#include "../../Archive/GZip/GZipHandler.h"
+#endif
+
+#ifdef FORMAT_TAR
+#include "../../Archive/Tar/TarHandler.h"
+#endif
+
+#ifdef FORMAT_ZIP
+#include "../../Archive/Zip/ZipHandler.h"
+#endif
+
+#ifndef EXCLUDE_COM
+#include "../Common/HandlerLoader.h"
+#endif
+
+static const char *kUpdateIsNotSupoorted =
+ "update operations are not supported for this archive";
+
+using namespace NCommandLineParser;
+using namespace NWindows;
+using namespace NCOM;
+using namespace NFile;
+using namespace NName;
+
+static const wchar_t *kTempArchiveFilePrefixString = L"7zi";
+static const wchar_t *kTempFolderPrefix = L"7zE";
+
+static const char *kIllegalFileNameMessage = "Illegal file name for temp archive";
+
+using namespace NUpdateArchive;
+
+static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream)
+{
+ CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+ return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
+}
+
+class COutMultiVolStream:
+ public IOutStream,
+ public CMyUnknownImp
+{
+ int _streamIndex; // required stream
+ UInt64 _offsetPos; // offset from start of _streamIndex index
+ UInt64 _absPos;
+ UInt64 _length;
+
+ struct CSubStreamInfo
+ {
+ CMyComPtr<IOutStream> Stream;
+ UString Name;
+ UInt64 Pos;
+ UInt64 RealSize;
+ };
+ CObjectVector<CSubStreamInfo> Streams;
+public:
+ // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+ CRecordVector<UInt64> Sizes;
+ UString Prefix;
+ CTempFiles *TempFiles;
+
+ void Init()
+ {
+ _streamIndex = 0;
+ _offsetPos = 0;
+ _absPos = 0;
+ _length = 0;
+ }
+
+ MY_UNKNOWN_IMP1(IOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+ STDMETHOD(SetSize)(Int64 newSize);
+};
+
+// static NSynchronization::CCriticalSection g_TempPathsCS;
+
+STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if(processedSize != NULL)
+ *processedSize = 0;
+ while(size > 0)
+ {
+ if (_streamIndex >= Streams.Size())
+ {
+ CSubStreamInfo subStream;
+
+ wchar_t temp[32];
+ ConvertUInt64ToString(_streamIndex + 1, temp);
+ UString res = temp;
+ while (res.Length() < 3)
+ res = UString(L'0') + res;
+ UString name = Prefix + res;
+ COutFileStream *streamSpec = new COutFileStream;
+ subStream.Stream = streamSpec;
+ if(!streamSpec->Create(name, false))
+ return ::GetLastError();
+ {
+ // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);
+ TempFiles->Paths.Add(name);
+ }
+
+ subStream.Pos = 0;
+ subStream.RealSize = 0;
+ subStream.Name = name;
+ Streams.Add(subStream);
+ continue;
+ }
+ CSubStreamInfo &subStream = Streams[_streamIndex];
+
+ int index = _streamIndex;
+ if (index >= Sizes.Size())
+ index = Sizes.Size() - 1;
+ UInt64 volSize = Sizes[index];
+
+ if (_offsetPos >= volSize)
+ {
+ _offsetPos -= volSize;
+ _streamIndex++;
+ continue;
+ }
+ if (_offsetPos != subStream.Pos)
+ {
+ // CMyComPtr<IOutStream> outStream;
+ // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
+ RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
+ subStream.Pos = _offsetPos;
+ }
+
+ UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos);
+ UInt32 realProcessed;
+ RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
+ data = (void *)((Byte *)data + realProcessed);
+ size -= realProcessed;
+ subStream.Pos += realProcessed;
+ _offsetPos += realProcessed;
+ _absPos += realProcessed;
+ if (_absPos > _length)
+ _length = _absPos;
+ if (_offsetPos > subStream.RealSize)
+ subStream.RealSize = _offsetPos;
+ if(processedSize != NULL)
+ *processedSize += realProcessed;
+ if (subStream.Pos == volSize)
+ {
+ _streamIndex++;
+ _offsetPos = 0;
+ }
+ if (realProcessed == 0 && curSize != 0)
+ return E_FAIL;
+ break;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ if(seekOrigin >= 3)
+ return STG_E_INVALIDFUNCTION;
+ switch(seekOrigin)
+ {
+ case STREAM_SEEK_SET:
+ _absPos = offset;
+ break;
+ case STREAM_SEEK_CUR:
+ _absPos += offset;
+ break;
+ case STREAM_SEEK_END:
+ _absPos = _length + offset;
+ break;
+ }
+ _offsetPos = _absPos;
+ if (newPosition != NULL)
+ *newPosition = _absPos;
+ _streamIndex = 0;
+ return S_OK;
+}
+
+STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize)
+{
+ if (newSize < 0)
+ return E_INVALIDARG;
+ int i = 0;
+ while (i < Streams.Size())
+ {
+ CSubStreamInfo &subStream = Streams[i++];
+ if ((UInt64)newSize < subStream.RealSize)
+ {
+ RINOK(subStream.Stream->SetSize(newSize));
+ subStream.RealSize = newSize;
+ break;
+ }
+ newSize -= subStream.RealSize;
+ }
+ while (i < Streams.Size())
+ {
+ {
+ CSubStreamInfo &subStream = Streams.Back();
+ subStream.Stream.Release();
+ NDirectory::DeleteFileAlways(subStream.Name);
+ }
+ Streams.DeleteBack();
+ }
+ _offsetPos = _absPos;
+ _streamIndex = 0;
+ _length = newSize;
+ return S_OK;
+}
+
+
+static HRESULT Compress(
+ const CActionSet &actionSet,
+ IInArchive *archive,
+ const CCompressionMethodMode &compressionMethod,
+ CArchivePath &archivePath,
+ const CObjectVector<CArchiveItem> &archiveItems,
+ bool stdInMode,
+ /* const UString & stdInFileName, */
+ bool stdOutMode,
+ const CObjectVector<CDirItem> &dirItems,
+ bool sfxMode,
+ const UString &sfxModule,
+ const CRecordVector<UInt64> &volumesSizes,
+ CTempFiles &tempFiles,
+ CUpdateErrorInfo &errorInfo,
+ IUpdateCallbackUI *callback)
+{
+ #ifndef EXCLUDE_COM
+ CHandlerLoader loader;
+ #endif
+
+ CMyComPtr<IOutArchive> outArchive;
+ if(archive != NULL)
+ {
+ CMyComPtr<IInArchive> archive2 = archive;
+ HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
+ if(result != S_OK)
+ throw kUpdateIsNotSupoorted;
+ }
+ else
+ {
+ #ifndef EXCLUDE_COM
+
+ if (loader.CreateHandler(compressionMethod.FilePath,
+ compressionMethod.ClassID, (void **)&outArchive, true) != S_OK)
+ throw kUpdateIsNotSupoorted;
+ #endif
+
+ #ifdef FORMAT_7Z
+ if (compressionMethod.Name.CompareNoCase(L"7z") == 0)
+ outArchive = new NArchive::N7z::CHandler;
+ #endif
+
+ #ifdef FORMAT_BZIP2
+ if (compressionMethod.Name.CompareNoCase(L"BZip2") == 0)
+ outArchive = new NArchive::NBZip2::CHandler;
+ #endif
+
+ #ifdef FORMAT_GZIP
+ if (compressionMethod.Name.CompareNoCase(L"GZip") == 0)
+ outArchive = new NArchive::NGZip::CHandler;
+ #endif
+
+ #ifdef FORMAT_TAR
+ if (compressionMethod.Name.CompareNoCase(L"Tar") == 0)
+ outArchive = new NArchive::NTar::CHandler;
+ #endif
+
+ #ifdef FORMAT_ZIP
+ if (compressionMethod.Name.CompareNoCase(L"Zip") == 0)
+ outArchive = new NArchive::NZip::CHandler;
+ #endif
+
+ }
+ if (outArchive == 0)
+ throw kUpdateIsNotSupoorted;
+
+ NFileTimeType::EEnum fileTimeType;
+ UInt32 value;
+ RINOK(outArchive->GetFileTimeType(&value));
+
+ switch(value)
+ {
+ case NFileTimeType::kWindows:
+ case NFileTimeType::kDOS:
+ case NFileTimeType::kUnix:
+ fileTimeType = NFileTimeType::EEnum(value);
+ break;
+ default:
+ return E_FAIL;
+ }
+
+ CObjectVector<CUpdatePair> updatePairs;
+ GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs); // must be done only once!!!
+
+ CObjectVector<CUpdatePair2> updatePairs2;
+ UpdateProduce(updatePairs, actionSet, updatePairs2);
+
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
+
+ updateCallbackSpec->StdInMode = stdInMode;
+ updateCallbackSpec->Callback = callback;
+ updateCallbackSpec->DirItems = &dirItems;
+ updateCallbackSpec->ArchiveItems = &archiveItems;
+ updateCallbackSpec->UpdatePairs = &updatePairs2;
+
+ CMyComPtr<ISequentialOutStream> outStream;
+
+ const UString &archiveName = archivePath.GetFinalPath();
+ if (!stdOutMode)
+ {
+ UString resultPath;
+ int pos;
+ if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
+ throw 1417161;
+ NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
+ }
+ if (volumesSizes.Size() == 0)
+ {
+ if (stdOutMode)
+ outStream = new CStdOutFileStream;
+ else
+ {
+ COutFileStream *outStreamSpec = new COutFileStream;
+ outStream = outStreamSpec;
+ bool isOK = false;
+ UString realPath;
+ for (int i = 0; i < (1 << 16); i++)
+ {
+ if (archivePath.Temp)
+ {
+ if (i > 0)
+ {
+ wchar_t s[32];
+ ConvertUInt64ToString(i, s);
+ archivePath.TempPostfix = s;
+ }
+ realPath = archivePath.GetTempPath();
+ }
+ else
+ realPath = archivePath.GetFinalPath();
+ if (outStreamSpec->Create(realPath, false))
+ {
+ tempFiles.Paths.Add(realPath);
+ isOK = true;
+ break;
+ }
+ if (::GetLastError() != ERROR_FILE_EXISTS)
+ break;
+ if (!archivePath.Temp)
+ break;
+ }
+ if (!isOK)
+ {
+ errorInfo.SystemError = ::GetLastError();
+ errorInfo.FileName = realPath;
+ errorInfo.Message = L"Can not open file";
+ return E_FAIL;
+ }
+ }
+ }
+ else
+ {
+ if (stdOutMode)
+ return E_FAIL;
+ COutMultiVolStream *volStreamSpec = new COutMultiVolStream;
+ outStream = volStreamSpec;
+ volStreamSpec->Sizes = volumesSizes;
+ volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");
+ volStreamSpec->TempFiles = &tempFiles;
+ volStreamSpec->Init();
+
+ /*
+ updateCallbackSpec->VolumesSizes = volumesSizes;
+ updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
+ if (!archivePath.VolExtension.IsEmpty())
+ updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;
+ */
+ }
+
+ RINOK(SetProperties(outArchive, compressionMethod.Properties));
+
+ if (sfxMode)
+ {
+ CInFileStream *sfxStreamSpec = new CInFileStream;
+ CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
+ if (!sfxStreamSpec->Open(sfxModule))
+ {
+ errorInfo.SystemError = ::GetLastError();
+ errorInfo.Message = L"Can't open sfx module";
+ errorInfo.FileName = sfxModule;
+ return E_FAIL;
+ }
+
+ CMyComPtr<ISequentialOutStream> sfxOutStream;
+ if (volumesSizes.Size() == 0)
+ sfxOutStream = outStream;
+ else
+ {
+ COutFileStream *outStreamSpec = new COutFileStream;
+ sfxOutStream = outStreamSpec;
+ UString realPath = archivePath.GetFinalPath();
+ if (!outStreamSpec->Create(realPath, false))
+ {
+ errorInfo.SystemError = ::GetLastError();
+ errorInfo.FileName = realPath;
+ errorInfo.Message = L"Can not open file";
+ return E_FAIL;
+ }
+ }
+ RINOK(CopyBlock(sfxStream, sfxOutStream));
+ }
+
+ HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(),
+ updateCallback);
+ callback->Finilize();
+ return result;
+}
+
+
+
+HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
+ IInArchive *archive,
+ const UString &defaultItemName,
+ const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
+ CObjectVector<CArchiveItem> &archiveItems)
+{
+ archiveItems.Clear();
+ UInt32 numItems;
+ RINOK(archive->GetNumberOfItems(&numItems));
+ archiveItems.Reserve(numItems);
+ for(UInt32 i = 0; i < numItems; i++)
+ {
+ CArchiveItem ai;
+
+ RINOK(GetArchiveItemPath(archive, i, ai.Name));
+ RINOK(IsArchiveItemFolder(archive, i, ai.IsDirectory));
+ ai.Censored = censor.CheckPath(ai.Name.IsEmpty() ? defaultItemName : ai.Name, !ai.IsDirectory);
+ RINOK(GetArchiveItemFileTime(archive, i,
+ archiveFileInfo.LastWriteTime, ai.LastWriteTime));
+
+ CPropVariant propertySize;
+ RINOK(archive->GetProperty(i, kpidSize, &propertySize));
+ ai.SizeIsDefined = (propertySize.vt != VT_EMPTY);
+ if (ai.SizeIsDefined)
+ ai.Size = ConvertPropVariantToUInt64(propertySize);
+
+ ai.IndexInServer = i;
+ archiveItems.Add(ai);
+ }
+ return S_OK;
+}
+
+
+static HRESULT UpdateWithItemLists(
+ CUpdateOptions &options,
+ IInArchive *archive,
+ const CObjectVector<CArchiveItem> &archiveItems,
+ const CObjectVector<CDirItem> &dirItems,
+ CTempFiles &tempFiles,
+ CUpdateErrorInfo &errorInfo,
+ IUpdateCallbackUI2 *callback)
+{
+ for(int i = 0; i < options.Commands.Size(); i++)
+ {
+ CUpdateArchiveCommand &command = options.Commands[i];
+ if (options.StdOutMode)
+ {
+ RINOK(callback->StartArchive(0, archive != 0));
+ }
+ else
+ {
+ RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(),
+ i == 0 && options.UpdateArchiveItself && archive != 0));
+ }
+
+ RINOK(Compress(command.ActionSet, archive,
+ options.MethodMode,
+ command.ArchivePath,
+ archiveItems,
+ options.StdInMode,
+ /* options.StdInFileName, */
+ options.StdOutMode,
+ dirItems,
+ options.SfxMode, options.SfxModule,
+ options.VolumesSizes,
+ tempFiles,
+ errorInfo, callback));
+
+ RINOK(callback->FinishArchive());
+ }
+ return S_OK;
+}
+
+#ifdef _WIN32
+class CCurrentDirRestorer
+{
+ UString m_CurrentDirectory;
+public:
+ CCurrentDirRestorer()
+ { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); }
+ ~CCurrentDirRestorer()
+ { RestoreDirectory();}
+ bool RestoreDirectory()
+ { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); }
+};
+#endif
+
+struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
+{
+ IUpdateCallbackUI2 *Callback;
+ HRESULT CheckBreak() { return Callback->CheckBreak(); }
+};
+
+HRESULT UpdateArchive(const NWildcard::CCensor &censor,
+ CUpdateOptions &options,
+ CUpdateErrorInfo &errorInfo,
+ IOpenCallbackUI *openCallback,
+ IUpdateCallbackUI2 *callback)
+{
+ if (options.StdOutMode && options.EMailMode)
+ return E_FAIL;
+
+ if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))
+ return E_NOTIMPL;
+
+ if (options.SfxMode)
+ {
+ CProperty property;
+ property.Name = L"rsfx";
+ property.Value = L"on";
+ options.MethodMode.Properties.Add(property);
+ if (options.SfxModule.IsEmpty())
+ {
+ errorInfo.Message = L"sfx file is not specified";
+ return E_FAIL;
+ }
+ UString name = options.SfxModule;
+ if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))
+ {
+ errorInfo.Message = L"can't find specified sfx module";
+ return E_FAIL;
+ }
+ }
+
+ const UString archiveName = options.ArchivePath.GetFinalPath();
+
+ UString defaultItemName;
+ NFind::CFileInfoW archiveFileInfo;
+
+ CArchiveLink archiveLink;
+ IInArchive *archive = 0;
+ if (NFind::FindFile(archiveName, archiveFileInfo))
+ {
+ if (archiveFileInfo.IsDirectory())
+ throw "there is no such archive";
+ if (options.VolumesSizes.Size() > 0)
+ return E_NOTIMPL;
+ HRESULT result = MyOpenArchive(archiveName, archiveLink, openCallback);
+ RINOK(callback->OpenResult(archiveName, result));
+ RINOK(result);
+ if (archiveLink.VolumePaths.Size() > 1)
+ {
+ errorInfo.SystemError = (DWORD)E_NOTIMPL;
+ errorInfo.Message = L"Updating for multivolume archives is not implemented";
+ return E_NOTIMPL;
+ }
+ archive = archiveLink.GetArchive();
+ defaultItemName = archiveLink.GetDefaultItemName();
+ }
+ else
+ {
+ /*
+ if (archiveType.IsEmpty())
+ throw "type of archive is not specified";
+ */
+ }
+
+ CObjectVector<CDirItem> dirItems;
+ if (options.StdInMode)
+ {
+ CDirItem item;
+ item.FullPath = item.Name = options.StdInFileName;
+ item.Size = (UInt64)(Int64)-1;
+ item.Attributes = 0;
+ SYSTEMTIME st;
+ FILETIME ft;
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &ft);
+ item.CreationTime = item.LastAccessTime = item.LastWriteTime = ft;
+ dirItems.Add(item);
+ }
+ else
+ {
+ bool needScanning = false;
+ for(int i = 0; i < options.Commands.Size(); i++)
+ if (options.Commands[i].ActionSet.NeedScanning())
+ needScanning = true;
+ if (needScanning)
+ {
+ CEnumDirItemUpdateCallback enumCallback;
+ enumCallback.Callback = callback;
+ RINOK(callback->StartScanning());
+ UStringVector errorPaths;
+ CRecordVector<DWORD> errorCodes;
+ HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes);
+ for (int i = 0; i < errorPaths.Size(); i++)
+ {
+ RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i]));
+ }
+ if(res != S_OK)
+ {
+ errorInfo.Message = L"Scanning error";
+ // errorInfo.FileName = errorPath;
+ return res;
+ }
+ RINOK(callback->FinishScanning());
+ }
+ }
+
+ UString tempDirPrefix;
+ bool usesTempDir = false;
+
+ #ifdef _WIN32
+ NDirectory::CTempDirectoryW tempDirectory;
+ if (options.EMailMode && options.EMailRemoveAfter)
+ {
+ tempDirectory.Create(kTempFolderPrefix);
+ tempDirPrefix = tempDirectory.GetPath();
+ NormalizeDirPathPrefix(tempDirPrefix);
+ usesTempDir = true;
+ }
+ #endif
+
+ CTempFiles tempFiles;
+
+ bool createTempFile = false;
+ if(!options.StdOutMode && options.UpdateArchiveItself)
+ {
+ CArchivePath &ap = options.Commands[0].ArchivePath;
+ ap = options.ArchivePath;
+ // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())
+ if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0)
+ {
+ createTempFile = true;
+ ap.Temp = true;
+ if (!options.WorkingDir.IsEmpty())
+ {
+ ap.TempPrefix = options.WorkingDir;
+ NormalizeDirPathPrefix(ap.TempPrefix);
+ }
+ }
+ }
+
+ for(int i = 0; i < options.Commands.Size(); i++)
+ {
+ CArchivePath &ap = options.Commands[i].ArchivePath;
+ if (usesTempDir)
+ {
+ // Check it
+ ap.Prefix = tempDirPrefix;
+ // ap.Temp = true;
+ // ap.TempPrefix = tempDirPrefix;
+ }
+ if (i > 0 || !createTempFile)
+ {
+ const UString &path = ap.GetFinalPath();
+ if (NFind::DoesFileExist(path))
+ {
+ errorInfo.SystemError = 0;
+ errorInfo.Message = L"File already exists";
+ errorInfo.FileName = path;
+ return E_FAIL;
+ }
+ }
+ }
+
+ CObjectVector<CArchiveItem> archiveItems;
+ if (archive != NULL)
+ {
+ RINOK(EnumerateInArchiveItems(censor,
+ archive, defaultItemName, archiveFileInfo, archiveItems));
+ }
+
+ RINOK(UpdateWithItemLists(options, archive, archiveItems, dirItems,
+ tempFiles, errorInfo, callback));
+
+ if (archive != NULL)
+ {
+ RINOK(archiveLink.Close());
+ archiveLink.Release();
+ }
+
+ tempFiles.Paths.Clear();
+ if(createTempFile)
+ {
+ try
+ {
+ CArchivePath &ap = options.Commands[0].ArchivePath;
+ const UString &tempPath = ap.GetTempPath();
+ if (archive != NULL)
+ if (!NDirectory::DeleteFileAlways(archiveName))
+ {
+ errorInfo.SystemError = ::GetLastError();
+ errorInfo.Message = L"delete file error";
+ errorInfo.FileName = archiveName;
+ return E_FAIL;
+ }
+ if (!NDirectory::MyMoveFile(tempPath, archiveName))
+ {
+ errorInfo.SystemError = ::GetLastError();
+ errorInfo.Message = L"move file error";
+ errorInfo.FileName = tempPath;
+ errorInfo.FileName2 = archiveName;
+ return E_FAIL;
+ }
+ }
+ catch(...)
+ {
+ throw;
+ }
+ }
+
+ #ifdef _WIN32
+ if (options.EMailMode)
+ {
+ NDLL::CLibrary mapiLib;
+ if (!mapiLib.Load(TEXT("Mapi32.dll")))
+ {
+ errorInfo.SystemError = ::GetLastError();
+ errorInfo.Message = L"can not load Mapi32.dll";
+ return E_FAIL;
+ }
+ LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)
+ mapiLib.GetProcAddress("MAPISendDocuments");
+ if (fnSend == 0)
+ {
+ errorInfo.SystemError = ::GetLastError();
+ errorInfo.Message = L"can not find MAPISendDocuments function";
+ return E_FAIL;
+ }
+ UStringVector fullPaths;
+ int i;
+ for(i = 0; i < options.Commands.Size(); i++)
+ {
+ CArchivePath &ap = options.Commands[i].ArchivePath;
+ UString arcPath;
+ if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))
+ {
+ errorInfo.SystemError = ::GetLastError();
+ return E_FAIL;
+ }
+ fullPaths.Add(arcPath);
+ }
+ CCurrentDirRestorer curDirRestorer;
+ for(i = 0; i < fullPaths.Size(); i++)
+ {
+ UString arcPath = fullPaths[i];
+ UString fileName = ExtractFileNameFromPath(arcPath);
+ AString path = GetAnsiString(arcPath);
+ AString name = GetAnsiString(fileName);
+ // Warning!!! MAPISendDocuments function changes Current directory
+ fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
+ }
+ }
+ #endif
+ return S_OK;
+}
+
diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h
new file mode 100755
index 00000000..465acc24
--- /dev/null
+++ b/CPP/7zip/UI/Common/Update.h
@@ -0,0 +1,158 @@
+// Update.h
+
+#ifndef __UPDATE_H
+#define __UPDATE_H
+
+#include "Common/Wildcard.h"
+#include "Windows/FileFind.h"
+#include "../../Archive/IArchive.h"
+
+#include "UpdateAction.h"
+#include "ArchiveOpenCallback.h"
+#include "UpdateCallback.h"
+#include "Property.h"
+
+struct CArchivePath
+{
+ UString Prefix; // path(folder) prefix including slash
+ UString Name; // base name
+ UString BaseExtension; // archive type extension or "exe" extension
+ UString VolExtension; // archive type extension for volumes
+
+ bool Temp;
+ UString TempPrefix; // path(folder) for temp location
+ UString TempPostfix;
+
+ CArchivePath(): Temp(false) {};
+
+ void ParseFromPath(const UString &path)
+ {
+ SplitPathToParts(path, Prefix, Name);
+ if (Name.IsEmpty())
+ return;
+ int dotPos = Name.ReverseFind(L'.');
+ if (dotPos <= 0)
+ return;
+ if (dotPos == Name.Length() - 1)
+ {
+ Name = Name.Left(dotPos);
+ BaseExtension.Empty();
+ return;
+ }
+ if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0)
+ {
+ BaseExtension = Name.Mid(dotPos + 1);
+ Name = Name.Left(dotPos);
+ }
+ else
+ BaseExtension.Empty();
+ }
+
+ UString GetPathWithoutExt() const
+ {
+ return Prefix + Name;
+ }
+
+ UString GetFinalPath() const
+ {
+ UString path = GetPathWithoutExt();
+ if (!BaseExtension.IsEmpty())
+ path += UString(L'.') + BaseExtension;
+ return path;
+ }
+
+
+ UString GetTempPath() const
+ {
+ UString path = TempPrefix + Name;
+ if (!BaseExtension.IsEmpty())
+ path += UString(L'.') + BaseExtension;
+ path += L".tmp";
+ path += TempPostfix;
+ return path;
+ }
+};
+
+struct CUpdateArchiveCommand
+{
+ CArchivePath ArchivePath;
+ NUpdateArchive::CActionSet ActionSet;
+};
+
+struct CCompressionMethodMode
+{
+ #ifndef EXCLUDE_COM
+ UString FilePath;
+ CLSID ClassID;
+ #else
+ UString Name;
+ #endif
+ CObjectVector<CProperty> Properties;
+};
+
+struct CUpdateOptions
+{
+ CCompressionMethodMode MethodMode;
+
+ CObjectVector<CUpdateArchiveCommand> Commands;
+ bool UpdateArchiveItself;
+ CArchivePath ArchivePath;
+
+ bool SfxMode;
+ UString SfxModule;
+
+ bool StdInMode;
+ UString StdInFileName;
+ bool StdOutMode;
+
+ bool EMailMode;
+ bool EMailRemoveAfter;
+ UString EMailAddress;
+
+ UString WorkingDir;
+
+ CUpdateOptions():
+ UpdateArchiveItself(true),
+ SfxMode(false),
+ StdInMode(false),
+ StdOutMode(false),
+ EMailMode(false),
+ EMailRemoveAfter(false)
+ {};
+ CRecordVector<UInt64> VolumesSizes;
+};
+
+struct CErrorInfo
+{
+ DWORD SystemError;
+ UString FileName;
+ UString FileName2;
+ UString Message;
+ // UStringVector ErrorPaths;
+ // CRecordVector<DWORD> ErrorCodes;
+ CErrorInfo(): SystemError(0) {};
+};
+
+struct CUpdateErrorInfo: public CErrorInfo
+{
+};
+
+struct IUpdateCallbackUI2: public IUpdateCallbackUI
+{
+ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) = 0;
+
+ virtual HRESULT StartScanning() = 0;
+ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) = 0;
+ virtual HRESULT FinishScanning() = 0;
+
+ virtual HRESULT StartArchive(const wchar_t *name, bool updating) = 0;
+ virtual HRESULT FinishArchive() = 0;
+};
+
+HRESULT UpdateArchive(const NWildcard::CCensor &censor,
+ CUpdateOptions &options,
+ CUpdateErrorInfo &errorInfo,
+ IOpenCallbackUI *openCallback,
+ IUpdateCallbackUI2 *callback);
+
+#endif
diff --git a/CPP/7zip/UI/Common/UpdateAction.cpp b/CPP/7zip/UI/Common/UpdateAction.cpp
new file mode 100755
index 00000000..5e3b5a10
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateAction.cpp
@@ -0,0 +1,64 @@
+// UpdateAction.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateAction.h"
+
+namespace NUpdateArchive {
+
+const CActionSet kAddActionSet =
+{
+ NPairAction::kCopy,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+ NPairAction::kCompress,
+ NPairAction::kCompress,
+ NPairAction::kCompress,
+ NPairAction::kCompress
+};
+
+const CActionSet kUpdateActionSet =
+{
+ NPairAction::kCopy,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+ NPairAction::kCopy,
+ NPairAction::kCompress
+};
+
+const CActionSet kFreshActionSet =
+{
+ NPairAction::kCopy,
+ NPairAction::kCopy,
+ NPairAction::kIgnore,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+ NPairAction::kCopy,
+ NPairAction::kCompress
+};
+
+const CActionSet kSynchronizeActionSet =
+{
+ NPairAction::kCopy,
+ NPairAction::kIgnore,
+ NPairAction::kCompress,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+};
+
+const CActionSet kDeleteActionSet =
+{
+ NPairAction::kCopy,
+ NPairAction::kIgnore,
+ NPairAction::kIgnore,
+ NPairAction::kIgnore,
+ NPairAction::kIgnore,
+ NPairAction::kIgnore,
+ NPairAction::kIgnore
+};
+
+}
diff --git a/CPP/7zip/UI/Common/UpdateAction.h b/CPP/7zip/UI/Common/UpdateAction.h
new file mode 100755
index 00000000..aa050975
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateAction.h
@@ -0,0 +1,57 @@
+// UpdateAction.h
+
+#ifndef __UPDATE_ACTION_H
+#define __UPDATE_ACTION_H
+
+namespace NUpdateArchive {
+
+ namespace NPairState
+ {
+ const int kNumValues = 7;
+ enum EEnum
+ {
+ kNotMasked = 0,
+ kOnlyInArchive,
+ kOnlyOnDisk,
+ kNewInArchive,
+ kOldInArchive,
+ kSameFiles,
+ kUnknowNewerFiles
+ };
+ }
+ namespace NPairAction
+ {
+ enum EEnum
+ {
+ kIgnore = 0,
+ kCopy,
+ kCompress,
+ kCompressAsAnti
+ };
+ }
+ struct CActionSet
+ {
+ NPairAction::EEnum StateActions[NPairState::kNumValues];
+ bool NeedScanning() const
+ {
+ int i;
+ for (i = 0; i < NPairState::kNumValues; i++)
+ if (StateActions[i] == NPairAction::kCompress)
+ return true;
+ for (i = 1; i < NPairState::kNumValues; i++)
+ if (StateActions[i] != NPairAction::kIgnore)
+ return true;
+ return false;
+ }
+ };
+ extern const CActionSet kAddActionSet;
+ extern const CActionSet kUpdateActionSet;
+ extern const CActionSet kFreshActionSet;
+ extern const CActionSet kSynchronizeActionSet;
+ extern const CActionSet kDeleteActionSet;
+};
+
+
+#endif
+
+
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
new file mode 100755
index 00000000..db3bf805
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -0,0 +1,258 @@
+// UpdateCallback.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateCallback.h"
+
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+#include "Common/Defs.h"
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../../Common/FileStreams.h"
+
+using namespace NWindows;
+
+CArchiveUpdateCallback::CArchiveUpdateCallback():
+ Callback(0),
+ StdInMode(false),
+ DirItems(0),
+ ArchiveItems(0),
+ UpdatePairs(0)
+ {}
+
+
+STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
+{
+ COM_TRY_BEGIN
+ return Callback->SetTotal(size);
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)
+{
+ COM_TRY_BEGIN
+ return Callback->SetCompleted(completeValue);
+ COM_TRY_END
+}
+
+/*
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidLastAccessTime, VT_FILETIME},
+ { NULL, kpidCreationTime, VT_FILETIME},
+ { NULL, kpidLastWriteTime, VT_FILETIME},
+ { NULL, kpidAttributes, VT_UI4},
+ { NULL, kpidIsAnti, VT_BOOL}
+};
+*/
+
+STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)
+{
+ return E_NOTIMPL;
+ /*
+ return CStatPropEnumerator::CreateEnumerator(kProperties,
+ sizeof(kProperties) / sizeof(kProperties[0]), enumerator);
+ */
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
+ Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
+{
+ COM_TRY_BEGIN
+ RINOK(Callback->CheckBreak());
+ const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
+ if(newData != NULL)
+ *newData = BoolToInt(updatePair.NewData);
+ if(newProperties != NULL)
+ *newProperties = BoolToInt(updatePair.NewProperties);
+ if(indexInArchive != NULL)
+ {
+ if (updatePair.ExistInArchive)
+ {
+ if (ArchiveItems == 0)
+ *indexInArchive = updatePair.ArchiveItemIndex;
+ else
+ *indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
+ }
+ else
+ *indexInArchive = UInt32(-1);
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
+ NWindows::NCOM::CPropVariant propVariant;
+
+ if (propID == kpidIsAnti)
+ {
+ propVariant = updatePair.IsAnti;
+ propVariant.Detach(value);
+ return S_OK;
+ }
+
+ if (updatePair.IsAnti)
+ {
+ switch(propID)
+ {
+ case kpidIsFolder:
+ case kpidPath:
+ break;
+ case kpidSize:
+ propVariant = (UInt64)0;
+ propVariant.Detach(value);
+ return S_OK;
+ default:
+ propVariant.Detach(value);
+ return S_OK;
+ }
+ }
+
+ if(updatePair.ExistOnDisk)
+ {
+ const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex];
+ switch(propID)
+ {
+ case kpidPath:
+ propVariant = dirItem.Name;
+ break;
+ case kpidIsFolder:
+ propVariant = dirItem.IsDirectory();
+ break;
+ case kpidSize:
+ propVariant = dirItem.Size;
+ break;
+ case kpidAttributes:
+ propVariant = dirItem.Attributes;
+ break;
+ case kpidLastAccessTime:
+ propVariant = dirItem.LastAccessTime;
+ break;
+ case kpidCreationTime:
+ propVariant = dirItem.CreationTime;
+ break;
+ case kpidLastWriteTime:
+ propVariant = dirItem.LastWriteTime;
+ break;
+ }
+ }
+ else
+ {
+ if (propID == kpidPath)
+ {
+ if (updatePair.NewNameIsDefined)
+ {
+ propVariant = updatePair.NewName;
+ propVariant.Detach(value);
+ return S_OK;
+ }
+ }
+ if (updatePair.ExistInArchive && Archive)
+ {
+ UInt32 indexInArchive;
+ if (ArchiveItems == 0)
+ indexInArchive = updatePair.ArchiveItemIndex;
+ else
+ indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
+ return Archive->GetProperty(indexInArchive, propID, value);
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
+{
+ COM_TRY_BEGIN
+ const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
+ if(!updatePair.NewData)
+ return E_FAIL;
+
+ RINOK(Callback->CheckBreak());
+ RINOK(Callback->Finilize());
+
+ if(updatePair.IsAnti)
+ {
+ return Callback->GetStream((*ArchiveItems)[updatePair.ArchiveItemIndex].Name, true);
+ }
+ const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex];
+ RINOK(Callback->GetStream(dirItem.Name, false));
+
+ if(dirItem.IsDirectory())
+ return S_OK;
+
+ if (StdInMode)
+ {
+ CStdInFileStream *inStreamSpec = new CStdInFileStream;
+ CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
+ *inStream = inStreamLoc.Detach();
+ }
+ else
+ {
+ CInFileStream *inStreamSpec = new CInFileStream;
+ CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
+ UString path = DirPrefix + dirItem.FullPath;
+ if(!inStreamSpec->Open(path))
+ {
+ return Callback->OpenFileError(path, ::GetLastError());
+ }
+ *inStream = inStreamLoc.Detach();
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult)
+{
+ COM_TRY_BEGIN
+ return Callback->SetOperationResult(operationResult);
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
+{
+ if (VolumesSizes.Size() == 0)
+ return S_FALSE;
+ if (index >= (UInt32)VolumesSizes.Size())
+ index = VolumesSizes.Size() - 1;
+ *size = VolumesSizes[index];
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
+{
+ COM_TRY_BEGIN
+ wchar_t temp[32];
+ ConvertUInt64ToString(index + 1, temp);
+ UString res = temp;
+ while (res.Length() < 2)
+ res = UString(L'0') + res;
+ UString fileName = VolName;
+ fileName += L'.';
+ fileName += res;
+ fileName += VolExt;
+ COutFileStream *streamSpec = new COutFileStream;
+ CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
+ if(!streamSpec->Create(fileName, false))
+ return ::GetLastError();
+ *volumeStream = streamLoc.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
+{
+ COM_TRY_BEGIN
+ return Callback->CryptoGetTextPassword2(passwordIsDefined, password);
+ COM_TRY_END
+}
diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h
new file mode 100755
index 00000000..8b14a9dc
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateCallback.h
@@ -0,0 +1,70 @@
+// UpdateCallback.h
+
+#ifndef __UPDATECALLBACK_H
+#define __UPDATECALLBACK_H
+
+#include "Common/MyCom.h"
+#include "Common/String.h"
+
+#include "../../IPassword.h"
+
+#include "../Common/UpdatePair.h"
+#include "../Common/UpdateProduce.h"
+
+struct IUpdateCallbackUI
+{
+ virtual HRESULT SetTotal(UInt64 size) = 0;
+ virtual HRESULT SetCompleted(const UInt64 *completeValue) = 0;
+ virtual HRESULT CheckBreak() = 0;
+ virtual HRESULT Finilize() = 0;
+ virtual HRESULT GetStream(const wchar_t *name, bool isAnti) = 0;
+ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) = 0;
+ virtual HRESULT SetOperationResult(Int32 operationResult) = 0;
+ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) = 0;
+ virtual HRESULT CloseProgress() { return S_OK; };
+};
+
+class CArchiveUpdateCallback:
+ public IArchiveUpdateCallback2,
+ public ICryptoGetTextPassword2,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP2(IArchiveUpdateCallback2,
+ ICryptoGetTextPassword2)
+
+ // IProgress
+ STDMETHOD(SetTotal)(UInt64 size);
+ STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+ // IUpdateCallback
+ STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);
+ STDMETHOD(GetUpdateItemInfo)(UInt32 index,
+ Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);
+ STDMETHOD(SetOperationResult)(Int32 operationResult);
+
+ STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);
+ STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);
+
+ STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
+
+public:
+ CRecordVector<UInt64> VolumesSizes;
+ UString VolName;
+ UString VolExt;
+
+ IUpdateCallbackUI *Callback;
+
+ UString DirPrefix;
+ bool StdInMode;
+ const CObjectVector<CDirItem> *DirItems;
+ const CObjectVector<CArchiveItem> *ArchiveItems;
+ const CObjectVector<CUpdatePair2> *UpdatePairs;
+ CMyComPtr<IInArchive> Archive;
+
+ CArchiveUpdateCallback();
+};
+
+#endif
diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp
new file mode 100755
index 00000000..dd51646f
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdatePair.cpp
@@ -0,0 +1,175 @@
+// UpdatePair.cpp
+
+#include "StdAfx.h"
+
+#include <time.h>
+
+#include "Common/Defs.h"
+#include "Windows/Time.h"
+
+#include "UpdatePair.h"
+#include "SortUtils.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+static int MyCompareTime(NFileTimeType::EEnum fileTimeType,
+ const FILETIME &time1, const FILETIME &time2)
+{
+ switch(fileTimeType)
+ {
+ case NFileTimeType::kWindows:
+ return ::CompareFileTime(&time1, &time2);
+ case NFileTimeType::kUnix:
+ {
+ UInt32 unixTime1, unixTime2;
+ if (!FileTimeToUnixTime(time1, unixTime1))
+ {
+ unixTime1 = 0;
+ // throw 4191614;
+ }
+ if (!FileTimeToUnixTime(time2, unixTime2))
+ {
+ unixTime2 = 0;
+ // throw 4191615;
+ }
+ return MyCompare(unixTime1, unixTime2);
+ }
+ case NFileTimeType::kDOS:
+ {
+ UInt32 dosTime1, dosTime2;
+ FileTimeToDosTime(time1, dosTime1);
+ FileTimeToDosTime(time2, dosTime2);
+ /*
+ if (!FileTimeToDosTime(time1, dosTime1))
+ throw 4191616;
+ if (!FileTimeToDosTime(time2, dosTime2))
+ throw 4191617;
+ */
+ return MyCompare(dosTime1, dosTime2);
+ }
+ }
+ throw 4191618;
+}
+
+static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:";
+
+/*
+static const char *kNotCensoredCollisionMessaged = "Internal file name collision:\n";
+static const char *kSameTimeChangedSizeCollisionMessaged =
+ "Collision between files with same date/time and different sizes:\n";
+*/
+
+static inline int MyFileNameCompare(const UString &s1, const UString &s2)
+{
+ return
+ #ifdef _WIN32
+ s1.CompareNoCase(s2);
+ #else
+ s1.Compare(s2);
+ #endif
+}
+
+static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices)
+{
+ for(int i = 0; i + 1 < indices.Size(); i++)
+ if (MyFileNameCompare(strings[indices[i]], strings[indices[i + 1]]) == 0)
+ {
+ UString message = kDuplicateFileNameMessage;
+ message += L"\n";
+ message += strings[indices[i]];
+ message += L"\n";
+ message += strings[indices[i + 1]];
+ throw message;
+ }
+}
+
+void GetUpdatePairInfoList(
+ const CObjectVector<CDirItem> &dirItems,
+ const CObjectVector<CArchiveItem> &archiveItems,
+ NFileTimeType::EEnum fileTimeType,
+ CObjectVector<CUpdatePair> &updatePairs)
+{
+ CIntVector dirIndices, archiveIndices;
+ UStringVector dirNames, archiveNames;
+
+ int numDirItems = dirItems.Size();
+ int i;
+ for(i = 0; i < numDirItems; i++)
+ dirNames.Add(dirItems[i].Name);
+ SortStringsToIndices(dirNames, dirIndices);
+ TestDuplicateString(dirNames, dirIndices);
+
+ int numArchiveItems = archiveItems.Size();
+ for(i = 0; i < numArchiveItems; i++)
+ archiveNames.Add(archiveItems[i].Name);
+ SortStringsToIndices(archiveNames, archiveIndices);
+ TestDuplicateString(archiveNames, archiveIndices);
+
+ int dirItemIndex = 0, archiveItemIndex = 0;
+ CUpdatePair pair;
+ while(dirItemIndex < numDirItems && archiveItemIndex < numArchiveItems)
+ {
+ int dirItemIndex2 = dirIndices[dirItemIndex],
+ archiveItemIndex2 = archiveIndices[archiveItemIndex];
+ const CDirItem &dirItem = dirItems[dirItemIndex2];
+ const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2];
+ int compareResult = MyFileNameCompare(dirItem.Name, archiveItem.Name);
+ if (compareResult < 0)
+ {
+ pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
+ pair.DirItemIndex = dirItemIndex2;
+ dirItemIndex++;
+ }
+ else if (compareResult > 0)
+ {
+ pair.State = archiveItem.Censored ?
+ NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked;
+ pair.ArchiveItemIndex = archiveItemIndex2;
+ archiveItemIndex++;
+ }
+ else
+ {
+ if (!archiveItem.Censored)
+ throw 1082022;; // TTString(kNotCensoredCollisionMessaged + dirItem.Name);
+ pair.DirItemIndex = dirItemIndex2;
+ pair.ArchiveItemIndex = archiveItemIndex2;
+ switch (MyCompareTime(fileTimeType, dirItem.LastWriteTime, archiveItem.LastWriteTime))
+ {
+ case -1:
+ pair.State = NUpdateArchive::NPairState::kNewInArchive;
+ break;
+ case 1:
+ pair.State = NUpdateArchive::NPairState::kOldInArchive;
+ break;
+ default:
+ if (archiveItem.SizeIsDefined)
+ if (dirItem.Size != archiveItem.Size)
+ // throw 1082034; // kSameTimeChangedSizeCollisionMessaged;
+ pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles;
+ else
+ pair.State = NUpdateArchive::NPairState::kSameFiles;
+ else
+ pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles;
+ }
+ dirItemIndex++;
+ archiveItemIndex++;
+ }
+ updatePairs.Add(pair);
+ }
+ for(;dirItemIndex < numDirItems; dirItemIndex++)
+ {
+ pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
+ pair.DirItemIndex = dirIndices[dirItemIndex];
+ updatePairs.Add(pair);
+ }
+ for(;archiveItemIndex < numArchiveItems; archiveItemIndex++)
+ {
+ int archiveItemIndex2 = archiveIndices[archiveItemIndex];
+ const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2];
+ pair.State = archiveItem.Censored ?
+ NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked;
+ pair.ArchiveItemIndex = archiveItemIndex2;
+ updatePairs.Add(pair);
+ }
+}
diff --git a/CPP/7zip/UI/Common/UpdatePair.h b/CPP/7zip/UI/Common/UpdatePair.h
new file mode 100755
index 00000000..f50a23f8
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdatePair.h
@@ -0,0 +1,24 @@
+// UpdatePair.h
+
+#ifndef __UPDATE_PAIR_H
+#define __UPDATE_PAIR_H
+
+#include "DirItem.h"
+#include "UpdateAction.h"
+
+#include "../../Archive/IArchive.h"
+
+struct CUpdatePair
+{
+ NUpdateArchive::NPairState::EEnum State;
+ int ArchiveItemIndex;
+ int DirItemIndex;
+};
+
+void GetUpdatePairInfoList(
+ const CObjectVector<CDirItem> &dirItems,
+ const CObjectVector<CArchiveItem> &archiveItems,
+ NFileTimeType::EEnum fileTimeType,
+ CObjectVector<CUpdatePair> &updatePairs);
+
+#endif
diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp
new file mode 100755
index 00000000..992bbeec
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -0,0 +1,63 @@
+// UpdateProduce.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateProduce.h"
+
+using namespace NUpdateArchive;
+
+static const char *kUpdateActionSetCollision =
+ "Internal collision in update action set";
+
+void UpdateProduce(
+ const CObjectVector<CUpdatePair> &updatePairs,
+ const NUpdateArchive::CActionSet &actionSet,
+ CObjectVector<CUpdatePair2> &operationChain)
+{
+ for(int i = 0; i < updatePairs.Size(); i++)
+ {
+ // CUpdateArchiveRange aRange;
+ const CUpdatePair &pair = updatePairs[i];
+
+ CUpdatePair2 pair2;
+ pair2.IsAnti = false;
+ pair2.ArchiveItemIndex = pair.ArchiveItemIndex;
+ pair2.DirItemIndex = pair.DirItemIndex;
+ pair2.ExistInArchive = (pair.State != NPairState::kOnlyOnDisk);
+ pair2.ExistOnDisk = (pair.State != NPairState::kOnlyInArchive);
+ switch(actionSet.StateActions[pair.State])
+ {
+ case NPairAction::kIgnore:
+ /*
+ if (pair.State != NPairState::kOnlyOnDisk)
+ IgnoreArchiveItem(m_ArchiveItems[pair.ArchiveItemIndex]);
+ // cout << "deleting";
+ */
+ break;
+ case NPairAction::kCopy:
+ {
+ if (pair.State == NPairState::kOnlyOnDisk)
+ throw kUpdateActionSetCollision;
+ pair2.NewData = pair2.NewProperties = false;
+ operationChain.Add(pair2);
+ break;
+ }
+ case NPairAction::kCompress:
+ {
+ if (pair.State == NPairState::kOnlyInArchive ||
+ pair.State == NPairState::kNotMasked)
+ throw kUpdateActionSetCollision;
+ pair2.NewData = pair2.NewProperties = true;
+ operationChain.Add(pair2);
+ break;
+ }
+ case NPairAction::kCompressAsAnti:
+ {
+ pair2.IsAnti = true;
+ pair2.NewData = pair2.NewProperties = true;
+ operationChain.Add(pair2);
+ break;
+ }
+ }
+ }
+}
diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h
new file mode 100755
index 00000000..8f58dab9
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateProduce.h
@@ -0,0 +1,31 @@
+// UpdateProduce.h
+
+#ifndef __UPDATE_PRODUCE_H
+#define __UPDATE_PRODUCE_H
+
+#include "UpdatePair.h"
+
+struct CUpdatePair2
+{
+ // bool OperationIsCompress;
+ bool NewData;
+ bool NewProperties;
+
+ bool ExistInArchive;
+ bool ExistOnDisk;
+ bool IsAnti;
+ int ArchiveItemIndex;
+ int DirItemIndex;
+
+ bool NewNameIsDefined;
+ UString NewName;
+
+ CUpdatePair2(): NewNameIsDefined(false) {}
+};
+
+void UpdateProduce(
+ const CObjectVector<CUpdatePair> &updatePairs,
+ const NUpdateArchive::CActionSet &actionSet,
+ CObjectVector<CUpdatePair2> &operationChain);
+
+#endif
diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp
new file mode 100755
index 00000000..8db6f4f1
--- /dev/null
+++ b/CPP/7zip/UI/Common/WorkDir.cpp
@@ -0,0 +1,64 @@
+// WorkDir.cpp
+
+#include "StdAfx.h"
+
+#include "WorkDir.h"
+
+#include "Common/StringConvert.h"
+#include "Common/Wildcard.h"
+
+#include "Windows/FileName.h"
+#include "Windows/FileDir.h"
+
+static inline UINT GetCurrentCodePage()
+ { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NName;
+
+UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path)
+{
+ NWorkDir::NMode::EEnum mode = workDirInfo.Mode;
+ if (workDirInfo.ForRemovableOnly)
+ {
+ mode = NWorkDir::NMode::kCurrent;
+ UString prefix = path.Left(3);
+ if (prefix[1] == L':' && prefix[2] == L'\\')
+ {
+ UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage()));
+ if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE)
+ mode = workDirInfo.Mode;
+ }
+ /*
+ CParsedPath parsedPath;
+ parsedPath.ParsePath(archiveName);
+ UINT driveType = GetDriveType(parsedPath.Prefix);
+ if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE))
+ mode = NZipSettings::NWorkDir::NMode::kCurrent;
+ */
+ }
+ switch(mode)
+ {
+ case NWorkDir::NMode::kCurrent:
+ {
+ return ExtractDirPrefixFromPath(path);
+ }
+ case NWorkDir::NMode::kSpecified:
+ {
+ UString tempDir = workDirInfo.Path;
+ NormalizeDirPathPrefix(tempDir);
+ return tempDir;
+ }
+ default:
+ {
+ UString tempDir;
+ if(!NFile::NDirectory::MyGetTempPath(tempDir))
+ throw 141717;
+ return tempDir;
+ }
+ }
+}
+
+
+
diff --git a/CPP/7zip/UI/Common/WorkDir.h b/CPP/7zip/UI/Common/WorkDir.h
new file mode 100755
index 00000000..0643d67a
--- /dev/null
+++ b/CPP/7zip/UI/Common/WorkDir.h
@@ -0,0 +1,10 @@
+// WorkDir.h
+
+#ifndef __WORKDIR_H
+#define __WORKDIR_H
+
+#include "ZipRegistry.h"
+
+UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path);
+
+#endif
diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp
new file mode 100755
index 00000000..e449d6b4
--- /dev/null
+++ b/CPP/7zip/UI/Common/ZipRegistry.cpp
@@ -0,0 +1,420 @@
+// ZipRegistry.cpp
+
+#include "StdAfx.h"
+
+#include "ZipRegistry.h"
+
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/Synchronization.h"
+#include "Windows/Registry.h"
+
+#include "Windows/FileDir.h"
+
+using namespace NWindows;
+using namespace NRegistry;
+
+static const TCHAR *kCUBasePath = TEXT("Software\\7-ZIP");
+
+// static const TCHAR *kArchiversKeyName = TEXT("Archivers");
+
+static NSynchronization::CCriticalSection g_RegistryOperationsCriticalSection;
+
+//////////////////////
+// ExtractionInfo
+
+static const TCHAR *kExtractionKeyName = TEXT("Extraction");
+
+static const TCHAR *kExtractionPathHistoryKeyName = TEXT("PathHistory");
+static const TCHAR *kExtractionExtractModeValueName = TEXT("ExtarctMode");
+static const TCHAR *kExtractionOverwriteModeValueName = TEXT("OverwriteMode");
+static const TCHAR *kExtractionShowPasswordValueName = TEXT("ShowPassword");
+
+static CSysString GetKeyPath(const CSysString &path)
+{
+ return CSysString(kCUBasePath) + CSysString('\\') + CSysString(path);
+}
+
+void SaveExtractionInfo(const NExtract::CInfo &info)
+{
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey extractionKey;
+ extractionKey.Create(HKEY_CURRENT_USER, GetKeyPath(kExtractionKeyName));
+ extractionKey.RecurseDeleteKey(kExtractionPathHistoryKeyName);
+ {
+ CKey pathHistoryKey;
+ pathHistoryKey.Create(extractionKey, kExtractionPathHistoryKeyName);
+ for(int i = 0; i < info.Paths.Size(); i++)
+ {
+ wchar_t numberString[16];
+ ConvertUInt64ToString(i, numberString);
+ pathHistoryKey.SetValue(numberString, info.Paths[i]);
+ }
+ }
+ extractionKey.SetValue(kExtractionExtractModeValueName, UInt32(info.PathMode));
+ extractionKey.SetValue(kExtractionOverwriteModeValueName, UInt32(info.OverwriteMode));
+ extractionKey.SetValue(kExtractionShowPasswordValueName, info.ShowPassword);
+}
+
+void ReadExtractionInfo(NExtract::CInfo &info)
+{
+ info.Paths.Clear();
+ info.PathMode = NExtract::NPathMode::kCurrentPathnames;
+ info.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
+ info.ShowPassword = false;
+
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey extractionKey;
+ if(extractionKey.Open(HKEY_CURRENT_USER, GetKeyPath(kExtractionKeyName), KEY_READ) != ERROR_SUCCESS)
+ return;
+
+ {
+ CKey pathHistoryKey;
+ if(pathHistoryKey.Open(extractionKey, kExtractionPathHistoryKeyName, KEY_READ) ==
+ ERROR_SUCCESS)
+ {
+ for (;;)
+ {
+ wchar_t numberString[16];
+ ConvertUInt64ToString(info.Paths.Size(), numberString);
+ UString path;
+ if (pathHistoryKey.QueryValue(numberString, path) != ERROR_SUCCESS)
+ break;
+ info.Paths.Add(path);
+ }
+ }
+ }
+ UInt32 extractModeIndex;
+ if (extractionKey.QueryValue(kExtractionExtractModeValueName, extractModeIndex) == ERROR_SUCCESS)
+ {
+ switch (extractModeIndex)
+ {
+ case NExtract::NPathMode::kFullPathnames:
+ case NExtract::NPathMode::kCurrentPathnames:
+ case NExtract::NPathMode::kNoPathnames:
+ info.PathMode = NExtract::NPathMode::EEnum(extractModeIndex);
+ break;
+ }
+ }
+ UInt32 overwriteModeIndex;
+ if (extractionKey.QueryValue(kExtractionOverwriteModeValueName, overwriteModeIndex) == ERROR_SUCCESS)
+ {
+ switch (overwriteModeIndex)
+ {
+ case NExtract::NOverwriteMode::kAskBefore:
+ case NExtract::NOverwriteMode::kWithoutPrompt:
+ case NExtract::NOverwriteMode::kSkipExisting:
+ case NExtract::NOverwriteMode::kAutoRename:
+ case NExtract::NOverwriteMode::kAutoRenameExisting:
+ info.OverwriteMode = NExtract::NOverwriteMode::EEnum(overwriteModeIndex);
+ break;
+ }
+ }
+ if (extractionKey.QueryValue(kExtractionShowPasswordValueName,
+ info.ShowPassword) != ERROR_SUCCESS)
+ info.ShowPassword = false;
+}
+
+///////////////////////////////////
+// CompressionInfo
+
+static const TCHAR *kCompressionKeyName = TEXT("Compression");
+
+static const TCHAR *kCompressionHistoryArchivesKeyName = TEXT("ArcHistory");
+static const TCHAR *kCompressionLevelValueName = TEXT("Level");
+static const TCHAR *kCompressionLastFormatValueName = TEXT("Archiver");
+static const TCHAR *kCompressionShowPasswordValueName = TEXT("ShowPassword");
+static const TCHAR *kCompressionEncryptHeadersValueName = TEXT("EncryptHeaders");
+// static const TCHAR *kCompressionMaximizeValueName = TEXT("Maximize");
+
+static const TCHAR *kCompressionOptionsKeyName = TEXT("Options");
+static const TCHAR *kSolid = TEXT("Solid");
+static const TCHAR *kMultiThread = TEXT("Multithread");
+
+static const WCHAR *kCompressionOptions = L"Options";
+static const TCHAR *kCompressionLevel = TEXT("Level");
+static const WCHAR *kCompressionMethod = L"Method";
+static const WCHAR *kEncryptionMethod = L"EncryptionMethod";
+static const TCHAR *kCompressionDictionary = TEXT("Dictionary");
+static const TCHAR *kCompressionOrder = TEXT("Order");
+
+
+static void SetRegString(CKey &key, const WCHAR *name, const UString &value)
+{
+ if (value.IsEmpty())
+ key.DeleteValue(name);
+ else
+ key.SetValue(name, value);
+}
+
+static void SetRegUInt32(CKey &key, const TCHAR *name, UInt32 value)
+{
+ if (value == (UInt32)-1)
+ key.DeleteValue(name);
+ else
+ key.SetValue(name, value);
+}
+
+static void GetRegString(CKey &key, const WCHAR *name, UString &value)
+{
+ if (key.QueryValue(name, value) != ERROR_SUCCESS)
+ value.Empty();
+}
+
+static void GetRegUInt32(CKey &key, const TCHAR *name, UInt32 &value)
+{
+ if (key.QueryValue(name, value) != ERROR_SUCCESS)
+ value = UInt32(-1);
+}
+
+void SaveCompressionInfo(const NCompression::CInfo &info)
+{
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+
+ CKey compressionKey;
+ compressionKey.Create(HKEY_CURRENT_USER, GetKeyPath(kCompressionKeyName));
+ compressionKey.RecurseDeleteKey(kCompressionHistoryArchivesKeyName);
+ {
+ CKey historyArchivesKey;
+ historyArchivesKey.Create(compressionKey, kCompressionHistoryArchivesKeyName);
+ for(int i = 0; i < info.HistoryArchives.Size(); i++)
+ {
+ wchar_t numberString[16];
+ ConvertUInt64ToString(i, numberString);
+ historyArchivesKey.SetValue(numberString, info.HistoryArchives[i]);
+ }
+ }
+
+ compressionKey.SetValue(kSolid, info.Solid);
+ compressionKey.SetValue(kMultiThread, info.MultiThread);
+ compressionKey.RecurseDeleteKey(kCompressionOptionsKeyName);
+ {
+ CKey optionsKey;
+ optionsKey.Create(compressionKey, kCompressionOptionsKeyName);
+ for(int i = 0; i < info.FormatOptionsVector.Size(); i++)
+ {
+ const NCompression::CFormatOptions &fo = info.FormatOptionsVector[i];
+ CKey formatKey;
+ formatKey.Create(optionsKey, fo.FormatID);
+
+ SetRegString(formatKey, kCompressionOptions, fo.Options);
+ SetRegString(formatKey, kCompressionMethod, fo.Method);
+ SetRegString(formatKey, kEncryptionMethod, fo.EncryptionMethod);
+
+ SetRegUInt32(formatKey, kCompressionLevel, fo.Level);
+ SetRegUInt32(formatKey, kCompressionDictionary, fo.Dictionary);
+ SetRegUInt32(formatKey, kCompressionOrder, fo.Order);
+ }
+ }
+
+ compressionKey.SetValue(kCompressionLevelValueName, UInt32(info.Level));
+ compressionKey.SetValue(kCompressionLastFormatValueName,
+ GetSystemString(info.ArchiveType));
+
+ compressionKey.SetValue(kCompressionShowPasswordValueName, info.ShowPassword);
+ compressionKey.SetValue(kCompressionEncryptHeadersValueName, info.EncryptHeaders);
+ // compressionKey.SetValue(kCompressionMaximizeValueName, info.Maximize);
+}
+
+static bool IsMultiProcessor()
+{
+ SYSTEM_INFO systemInfo;
+ GetSystemInfo(&systemInfo);
+ return systemInfo.dwNumberOfProcessors > 1;
+}
+
+void ReadCompressionInfo(NCompression::CInfo &info)
+{
+ info.HistoryArchives.Clear();
+
+ info.Solid = true;
+ info.MultiThread = IsMultiProcessor();
+ info.FormatOptionsVector.Clear();
+
+ info.Level = 5;
+ info.ArchiveType = L"7z";
+ // definedStatus.Maximize = false;
+ info.ShowPassword = false;
+ info.EncryptHeaders = false;
+
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey compressionKey;
+
+ if(compressionKey.Open(HKEY_CURRENT_USER,
+ GetKeyPath(kCompressionKeyName), KEY_READ) != ERROR_SUCCESS)
+ return;
+
+ {
+ CKey historyArchivesKey;
+ if(historyArchivesKey.Open(compressionKey, kCompressionHistoryArchivesKeyName, KEY_READ) ==
+ ERROR_SUCCESS)
+ {
+ for (;;)
+ {
+ wchar_t numberString[16];
+ ConvertUInt64ToString(info.HistoryArchives.Size(), numberString);
+ UString path;
+ if (historyArchivesKey.QueryValue(numberString, path) != ERROR_SUCCESS)
+ break;
+ info.HistoryArchives.Add(path);
+ }
+ }
+ }
+
+
+ bool solid = false;
+ if (compressionKey.QueryValue(kSolid, solid) == ERROR_SUCCESS)
+ info.Solid = solid;
+ bool multiThread = false;
+ if (compressionKey.QueryValue(kMultiThread, multiThread) == ERROR_SUCCESS)
+ info.MultiThread = multiThread;
+
+ {
+ CKey optionsKey;
+ if(optionsKey.Open(compressionKey, kCompressionOptionsKeyName, KEY_READ) ==
+ ERROR_SUCCESS)
+ {
+ CSysStringVector formatIDs;
+ optionsKey.EnumKeys(formatIDs);
+ for(int i = 0; i < formatIDs.Size(); i++)
+ {
+ CKey formatKey;
+ NCompression::CFormatOptions fo;
+ fo.FormatID = formatIDs[i];
+ if(formatKey.Open(optionsKey, fo.FormatID, KEY_READ) == ERROR_SUCCESS)
+ {
+ GetRegString(formatKey, kCompressionOptions, fo.Options);
+ GetRegString(formatKey, kCompressionMethod, fo.Method);
+ GetRegString(formatKey, kEncryptionMethod, fo.EncryptionMethod);
+
+ GetRegUInt32(formatKey, kCompressionLevel, fo.Level);
+ GetRegUInt32(formatKey, kCompressionDictionary, fo.Dictionary);
+ GetRegUInt32(formatKey, kCompressionOrder, fo.Order);
+
+ info.FormatOptionsVector.Add(fo);
+ }
+
+ }
+ }
+ }
+
+ UInt32 level;
+ if (compressionKey.QueryValue(kCompressionLevelValueName, level) == ERROR_SUCCESS)
+ info.Level = level;
+ CSysString archiveType;
+ if (compressionKey.QueryValue(kCompressionLastFormatValueName, archiveType) == ERROR_SUCCESS)
+ info.ArchiveType = GetUnicodeString(archiveType);
+ if (compressionKey.QueryValue(kCompressionShowPasswordValueName,
+ info.ShowPassword) != ERROR_SUCCESS)
+ info.ShowPassword = false;
+ if (compressionKey.QueryValue(kCompressionEncryptHeadersValueName,
+ info.EncryptHeaders) != ERROR_SUCCESS)
+ info.EncryptHeaders = false;
+ /*
+ if (compressionKey.QueryValue(kCompressionLevelValueName, info.Maximize) == ERROR_SUCCESS)
+ definedStatus.Maximize = true;
+ */
+}
+
+
+///////////////////////////////////
+// WorkDirInfo
+
+static const TCHAR *kOptionsInfoKeyName = TEXT("Options");
+
+static const TCHAR *kWorkDirTypeValueName = TEXT("WorkDirType");
+static const WCHAR *kWorkDirPathValueName = L"WorkDirPath";
+static const TCHAR *kTempRemovableOnlyValueName = TEXT("TempRemovableOnly");
+static const TCHAR *kCascadedMenuValueName = TEXT("CascadedMenu");
+static const TCHAR *kContextMenuValueName = TEXT("ContextMenu");
+
+void SaveWorkDirInfo(const NWorkDir::CInfo &info)
+{
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey optionsKey;
+ optionsKey.Create(HKEY_CURRENT_USER, GetKeyPath(kOptionsInfoKeyName));
+ optionsKey.SetValue(kWorkDirTypeValueName, UInt32(info.Mode));
+ optionsKey.SetValue(kWorkDirPathValueName, info.Path);
+ optionsKey.SetValue(kTempRemovableOnlyValueName, info.ForRemovableOnly);
+}
+
+void ReadWorkDirInfo(NWorkDir::CInfo &info)
+{
+ info.SetDefault();
+
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey optionsKey;
+ if(optionsKey.Open(HKEY_CURRENT_USER, GetKeyPath(kOptionsInfoKeyName), KEY_READ) != ERROR_SUCCESS)
+ return;
+
+ UInt32 dirType;
+ if (optionsKey.QueryValue(kWorkDirTypeValueName, dirType) != ERROR_SUCCESS)
+ return;
+ switch (dirType)
+ {
+ case NWorkDir::NMode::kSystem:
+ case NWorkDir::NMode::kCurrent:
+ case NWorkDir::NMode::kSpecified:
+ info.Mode = NWorkDir::NMode::EEnum(dirType);
+ }
+ UString sysWorkDir;
+ if (optionsKey.QueryValue(kWorkDirPathValueName, sysWorkDir) != ERROR_SUCCESS)
+ {
+ info.Path.Empty();
+ if (info.Mode == NWorkDir::NMode::kSpecified)
+ info.Mode = NWorkDir::NMode::kSystem;
+ }
+ info.Path = GetUnicodeString(sysWorkDir);
+ if (optionsKey.QueryValue(kTempRemovableOnlyValueName, info.ForRemovableOnly) != ERROR_SUCCESS)
+ info.SetForRemovableOnlyDefault();
+}
+
+static void SaveOption(const TCHAR *value, bool enabled)
+{
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey optionsKey;
+ optionsKey.Create(HKEY_CURRENT_USER, GetKeyPath(kOptionsInfoKeyName));
+ optionsKey.SetValue(value, enabled);
+}
+
+static bool ReadOption(const TCHAR *value, bool defaultValue)
+{
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey optionsKey;
+ if(optionsKey.Open(HKEY_CURRENT_USER, GetKeyPath(kOptionsInfoKeyName), KEY_READ) != ERROR_SUCCESS)
+ return defaultValue;
+ bool enabled;
+ if (optionsKey.QueryValue(value, enabled) != ERROR_SUCCESS)
+ return defaultValue;
+ return enabled;
+}
+
+void SaveCascadedMenu(bool show)
+ { SaveOption(kCascadedMenuValueName, show); }
+bool ReadCascadedMenu()
+ { return ReadOption(kCascadedMenuValueName, true); }
+
+
+static void SaveValue(const TCHAR *value, UInt32 valueToWrite)
+{
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey optionsKey;
+ optionsKey.Create(HKEY_CURRENT_USER, GetKeyPath(kOptionsInfoKeyName));
+ optionsKey.SetValue(value, valueToWrite);
+}
+
+static bool ReadValue(const TCHAR *value, UInt32 &result)
+{
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey optionsKey;
+ if(optionsKey.Open(HKEY_CURRENT_USER, GetKeyPath(kOptionsInfoKeyName), KEY_READ) != ERROR_SUCCESS)
+ return false;
+ return (optionsKey.QueryValue(value, result) == ERROR_SUCCESS);
+}
+
+void SaveContextMenuStatus(UInt32 value)
+ { SaveValue(kContextMenuValueName, value); }
+
+bool ReadContextMenuStatus(UInt32 &value)
+ { return ReadValue(kContextMenuValueName, value); }
diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h
new file mode 100755
index 00000000..30e7ee44
--- /dev/null
+++ b/CPP/7zip/UI/Common/ZipRegistry.h
@@ -0,0 +1,99 @@
+// ZipRegistry.h
+
+#ifndef __ZIPREGISTRY_H
+#define __ZIPREGISTRY_H
+
+#include "Common/String.h"
+#include "Common/Types.h"
+#include "ExtractMode.h"
+
+namespace NExtract
+{
+ struct CInfo
+ {
+ NPathMode::EEnum PathMode;
+ NOverwriteMode::EEnum OverwriteMode;
+ UStringVector Paths;
+ bool ShowPassword;
+ };
+}
+
+namespace NCompression {
+
+ struct CFormatOptions
+ {
+ CSysString FormatID;
+ UString Options;
+ UString Method;
+ UString EncryptionMethod;
+ UInt32 Level;
+ UInt32 Dictionary;
+ UInt32 Order;
+ void ResetForLevelChange()
+ {
+ Level = Dictionary = Order = UInt32(-1);
+ Method.Empty();
+ // EncryptionMethod.Empty();
+ // Options.Empty();
+ }
+ CFormatOptions() { ResetForLevelChange(); }
+ };
+
+ struct CInfo
+ {
+ UStringVector HistoryArchives;
+ // bool LevelIsDefined;
+ UInt32 Level;
+ UString ArchiveType;
+
+ bool Solid;
+ bool MultiThread;
+ CObjectVector<CFormatOptions> FormatOptionsVector;
+
+ bool ShowPassword;
+ bool EncryptHeaders;
+ };
+}
+
+namespace NWorkDir{
+
+ namespace NMode
+ {
+ enum EEnum
+ {
+ kSystem,
+ kCurrent,
+ kSpecified
+ };
+ }
+ struct CInfo
+ {
+ NMode::EEnum Mode;
+ UString Path;
+ bool ForRemovableOnly;
+ void SetForRemovableOnlyDefault() { ForRemovableOnly = true; }
+ void SetDefault()
+ {
+ Mode = NMode::kSystem;
+ Path.Empty();
+ SetForRemovableOnlyDefault();
+ }
+ };
+}
+
+void SaveExtractionInfo(const NExtract::CInfo &info);
+void ReadExtractionInfo(NExtract::CInfo &info);
+
+void SaveCompressionInfo(const NCompression::CInfo &info);
+void ReadCompressionInfo(NCompression::CInfo &info);
+
+void SaveWorkDirInfo(const NWorkDir::CInfo &info);
+void ReadWorkDirInfo(NWorkDir::CInfo &info);
+
+void SaveCascadedMenu(bool enabled);
+bool ReadCascadedMenu();
+
+void SaveContextMenuStatus(UInt32 value);
+bool ReadContextMenuStatus(UInt32 &value);
+
+#endif
diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp
new file mode 100755
index 00000000..e457008c
--- /dev/null
+++ b/CPP/7zip/UI/Console/Console.dsp
@@ -0,0 +1,667 @@
+# Microsoft Developer Studio Project File - Name="Console" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Console - Win32 DebugU
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Console.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Console.mak" CFG="Console - Win32 DebugU"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Console - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Console - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "Console - Win32 ReleaseU" (based on "Win32 (x86) Console Application")
+!MESSAGE "Console - Win32 DebugU" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Console - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\UTIL\7z.exe" /OPT:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Console - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "Console - Win32 ReleaseU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Console___Win32_ReleaseU"
+# PROP BASE Intermediate_Dir "Console___Win32_ReleaseU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseU"
+# PROP Intermediate_Dir "ReleaseU"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\UTIL\7z.exe"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\UTIL\7zn.exe" /OPT:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Console - Win32 DebugU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Console___Win32_DebugU"
+# PROP BASE Intermediate_Dir "Console___Win32_DebugU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugU"
+# PROP Intermediate_Dir "DebugU"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MT" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Console - Win32 Release"
+# Name "Console - Win32 Debug"
+# Name "Console - Win32 ReleaseU"
+# Name "Console - Win32 DebugU"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Console"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ConsoleClose.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ConsoleClose.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ExtractCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ExtractCallbackConsole.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\List.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\List.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainAr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OpenCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OpenCallbackConsole.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PercentPrinter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PercentPrinter.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\UpdateCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\UpdateCallbackConsole.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\UserInputUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\UserInputUtils.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Error.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\MemoryLock.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\MemoryLock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Registry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Registry.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Time.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\Alloc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Alloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Buffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ComTry.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Exception.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ListFileUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ListFileUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyCom.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdOutStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "UI Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\ArchiveCommandLine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveCommandLine.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveExtractCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveOpenCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveOpenCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiverInfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiverInfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\CompressionMode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DefaultName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DefaultName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DirItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\EnumDirItems.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\EnumDirItems.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExitCode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\Extract.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\Extract.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExtractingFilePath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExtractingFilePath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\HandlerLoader.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\IFileExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\OpenArchive.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\OpenArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\Property.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\PropIDUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\PropIDUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SetProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SetProperties.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SortUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SortUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\TempFiles.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\TempFiles.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\Update.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\Update.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateAction.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateAction.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdatePair.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdatePair.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateProduce.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateProduce.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\WorkDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\WorkDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ZipRegistry.h
+# End Source File
+# End Group
+# Begin Group "7-zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\FilePathAutoRename.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FilePathAutoRename.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/CPP/7zip/UI/Console/Console.dsw b/CPP/7zip/UI/Console/Console.dsw
new file mode 100755
index 00000000..0d93da2f
--- /dev/null
+++ b/CPP/7zip/UI/Console/Console.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Console"=".\Console.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp
new file mode 100755
index 00000000..a514c12a
--- /dev/null
+++ b/CPP/7zip/UI/Console/ConsoleClose.cpp
@@ -0,0 +1,65 @@
+// ConsoleClose.cpp
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#include "ConsoleClose.h"
+
+static int g_BreakCounter = 0;
+static const int kBreakAbortThreshold = 2;
+
+namespace NConsoleClose {
+
+static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
+{
+ if (ctrlType == CTRL_LOGOFF_EVENT)
+ {
+ // printf("\nCTRL_LOGOFF_EVENT\n");
+ return TRUE;
+ }
+
+ g_BreakCounter++;
+ if (g_BreakCounter < kBreakAbortThreshold)
+ return TRUE;
+ return FALSE;
+ /*
+ switch(ctrlType)
+ {
+ case CTRL_C_EVENT:
+ case CTRL_BREAK_EVENT:
+ if (g_BreakCounter < kBreakAbortThreshold)
+ return TRUE;
+ }
+ return FALSE;
+ */
+}
+
+bool TestBreakSignal()
+{
+ /*
+ if (g_BreakCounter > 0)
+ return true;
+ */
+ return (g_BreakCounter > 0);
+}
+
+void CheckCtrlBreak()
+{
+ if (TestBreakSignal())
+ throw CCtrlBreakException();
+}
+
+CCtrlHandlerSetter::CCtrlHandlerSetter()
+{
+ if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE))
+ throw "SetConsoleCtrlHandler fails";
+}
+
+CCtrlHandlerSetter::~CCtrlHandlerSetter()
+{
+ if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE))
+ throw "SetConsoleCtrlHandler fails";
+}
+
+}
diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h
new file mode 100755
index 00000000..3c5fd55d
--- /dev/null
+++ b/CPP/7zip/UI/Console/ConsoleClose.h
@@ -0,0 +1,24 @@
+// ConsoleCloseUtils.h
+
+#ifndef __CONSOLECLOSEUTILS_H
+#define __CONSOLECLOSEUTILS_H
+
+namespace NConsoleClose {
+
+bool TestBreakSignal();
+
+class CCtrlHandlerSetter
+{
+public:
+ CCtrlHandlerSetter();
+ virtual ~CCtrlHandlerSetter();
+};
+
+class CCtrlBreakException
+{};
+
+void CheckCtrlBreak();
+
+}
+
+#endif
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
new file mode 100755
index 00000000..9bd605ec
--- /dev/null
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
@@ -0,0 +1,235 @@
+// ExtractCallbackConsole.h
+
+#include "StdAfx.h"
+
+#include "ExtractCallbackConsole.h"
+#include "UserInputUtils.h"
+#include "ConsoleClose.h"
+
+#include "Common/Wildcard.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/FileFind.h"
+#include "Windows/Time.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+#include "Windows/Error.h"
+#include "Windows/PropVariantConversions.h"
+
+#include "../../Common/FilePathAutoRename.h"
+
+#include "../Common/ExtractingFilePath.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDirectory;
+
+static const char *kTestingString = "Testing ";
+static const char *kExtractingString = "Extracting ";
+static const char *kSkippingString = "Skipping ";
+
+static const char *kCantAutoRename = "can not create file with auto name\n";
+static const char *kCantRenameFile = "can not rename existing file\n";
+static const char *kCantDeleteOutputFile = "can not delete output file ";
+static const char *kError = "ERROR: ";
+static const char *kMemoryExceptionMessage = "Can't allocate required memory!";
+
+static const char *kProcessing = "Processing archive: ";
+static const char *kEverythingIsOk = "Everything is Ok";
+static const char *kNoFiles = "No files to process";
+
+static const char *kUnsupportedMethod = "Unsupported Method";
+static const char *kCrcFailed = "CRC Failed";
+static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";
+static const char *kDataError = "Data Error";
+static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";
+static const char *kUnknownError = "Unknown Error";
+
+STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64)
+{
+ if (NConsoleClose::TestBreakSignal())
+ return E_ABORT;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *)
+{
+ if (NConsoleClose::TestBreakSignal())
+ return E_ABORT;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
+ const wchar_t *existName, const FILETIME *, const UInt64 *,
+ const wchar_t *newName, const FILETIME *, const UInt64 *,
+ Int32 *answer)
+{
+ (*OutStream) << "file " << existName <<
+ "\nalready exists. Overwrite with " << endl;
+ (*OutStream) << newName;
+
+ NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream);
+
+ switch(overwriteAnswer)
+ {
+ case NUserAnswerMode::kQuit:
+ return E_ABORT;
+ case NUserAnswerMode::kNo:
+ *answer = NOverwriteAnswer::kNo;
+ break;
+ case NUserAnswerMode::kNoAll:
+ *answer = NOverwriteAnswer::kNoToAll;
+ break;
+ case NUserAnswerMode::kYesAll:
+ *answer = NOverwriteAnswer::kYesToAll;
+ break;
+ case NUserAnswerMode::kYes:
+ *answer = NOverwriteAnswer::kYes;
+ break;
+ case NUserAnswerMode::kAutoRename:
+ *answer = NOverwriteAnswer::kAutoRename;
+ break;
+ default:
+ return E_FAIL;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 askExtractMode, const UInt64 *position)
+{
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract:
+ (*OutStream) << kExtractingString;
+ break;
+ case NArchive::NExtract::NAskMode::kTest:
+ (*OutStream) << kTestingString;
+ break;
+ case NArchive::NExtract::NAskMode::kSkip:
+ (*OutStream) << kSkippingString;
+ break;
+ };
+ (*OutStream) << name;
+ if (position != 0)
+ (*OutStream) << " <" << *position << ">";
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)
+{
+ (*OutStream) << message << endl;
+ NumFileErrorsInCurrentArchive++;
+ NumFileErrors++;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted)
+{
+ switch(operationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kOK:
+ break;
+ default:
+ {
+ NumFileErrorsInCurrentArchive++;
+ NumFileErrors++;
+ (*OutStream) << " ";
+ switch(operationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
+ (*OutStream) << kUnsupportedMethod;
+ break;
+ case NArchive::NExtract::NOperationResult::kCRCError:
+ (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed);
+ break;
+ case NArchive::NExtract::NOperationResult::kDataError:
+ (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError);
+ break;
+ default:
+ (*OutStream) << kUnknownError;
+ }
+ }
+ }
+ (*OutStream) << endl;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)
+{
+ if (!PasswordIsDefined)
+ {
+ Password = GetPassword(OutStream);
+ PasswordIsDefined = true;
+ }
+ CMyComBSTR tempName(Password);
+ *password = tempName.Detach();
+ return S_OK;
+}
+
+HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name)
+{
+ NumArchives++;
+ NumFileErrorsInCurrentArchive = 0;
+ (*OutStream) << endl << kProcessing << name << endl;
+ return S_OK;
+}
+
+HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted)
+{
+ (*OutStream) << endl;
+ if (result != S_OK)
+ {
+ (*OutStream) << "Error: ";
+ if (encrypted)
+ (*OutStream) << "Can not open encrypted archive. Wrong password?";
+ else
+ (*OutStream) << "Can not open file as archive";
+ (*OutStream) << endl;
+ NumArchiveErrors++;
+ }
+ return S_OK;
+}
+
+HRESULT CExtractCallbackConsole::ThereAreNoFiles()
+{
+ (*OutStream) << endl << kNoFiles << endl;
+ return S_OK;
+}
+
+HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
+{
+ if (result == S_OK)
+ {
+ (*OutStream) << endl;
+ if (NumFileErrorsInCurrentArchive == 0)
+ (*OutStream) << kEverythingIsOk << endl;
+ else
+ {
+ NumArchiveErrors++;
+ (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl;
+ }
+ }
+ if (result == S_OK)
+ return result;
+ NumArchiveErrors++;
+ if (result == E_ABORT || result == ERROR_DISK_FULL)
+ return result;
+ (*OutStream) << endl << kError;
+ if (result == E_OUTOFMEMORY)
+ (*OutStream) << kMemoryExceptionMessage;
+ else
+ {
+ UString message;
+ NError::MyFormatMessage(result, message);
+ (*OutStream) << message;
+ }
+ (*OutStream) << endl;
+ return S_OK;
+}
+
+HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
+{
+ PasswordIsDefined = true;
+ Password = password;
+ return S_OK;
+}
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
new file mode 100755
index 00000000..5b45106a
--- /dev/null
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
@@ -0,0 +1,65 @@
+// ExtractCallbackConsole.h
+
+#ifndef __EXTRACTCALLBACKCONSOLE_H
+#define __EXTRACTCALLBACKCONSOLE_H
+
+#include "Common/String.h"
+#include "Common/StdOutStream.h"
+#include "../../Common/FileStreams.h"
+#include "../../IPassword.h"
+#include "../../Archive/IArchive.h"
+#include "../Common/ArchiveExtractCallback.h"
+
+class CExtractCallbackConsole:
+ public IExtractCallbackUI,
+ public ICryptoGetTextPassword,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP2(IFolderArchiveExtractCallback, ICryptoGetTextPassword)
+
+ STDMETHOD(SetTotal)(UInt64 total);
+ STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+ // IFolderArchiveExtractCallback
+ 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, Int32 askExtractMode, const UInt64 *position);
+
+ STDMETHOD(MessageError)(const wchar_t *message);
+ STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);
+
+ // ICryptoGetTextPassword
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+
+ HRESULT BeforeOpen(const wchar_t *name);
+ HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);
+ HRESULT ThereAreNoFiles();
+ HRESULT ExtractResult(HRESULT result);
+
+ HRESULT SetPassword(const UString &password);
+
+public:
+ bool PasswordIsDefined;
+ UString Password;
+
+ UInt64 NumArchives;
+ UInt64 NumArchiveErrors;
+ UInt64 NumFileErrors;
+ UInt64 NumFileErrorsInCurrentArchive;
+
+ CStdOutStream *OutStream;
+
+ void Init()
+ {
+ NumArchives = 0;
+ NumArchiveErrors = 0;
+ NumFileErrors = 0;
+ NumFileErrorsInCurrentArchive = 0;
+ }
+
+};
+
+#endif
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
new file mode 100755
index 00000000..6001e114
--- /dev/null
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -0,0 +1,532 @@
+// List.cpp
+
+#include "StdAfx.h"
+
+#include "List.h"
+#include "ConsoleClose.h"
+
+#include "Common/StringConvert.h"
+#include "Common/StdOutStream.h"
+#include "Common/IntToString.h"
+#include "Common/MyCom.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariantConversions.h"
+#include "Windows/FileDir.h"
+
+#include "../../Archive/IArchive.h"
+
+#include "../Common/PropIDUtils.h"
+#include "../Common/OpenArchive.h"
+
+#include "OpenCallbackConsole.h"
+
+using namespace NWindows;
+
+struct CPropIdToName
+{
+ PROPID PropID;
+ const wchar_t *Name;
+};
+
+static CPropIdToName kPropIdToName[] =
+{
+ { kpidPath, L"Path" },
+ { kpidName, L"Name" },
+ { kpidIsFolder, L"Folder" },
+ { kpidSize, L"Size" },
+ { kpidPackedSize, L"Packed Size" },
+ { kpidAttributes, L"Attributes" },
+ { kpidCreationTime, L"Created" },
+ { kpidLastAccessTime, L"Accessed" },
+ { kpidLastWriteTime, L"Modified" },
+ { kpidSolid, L"Solid" },
+ { kpidCommented, L"Commented" },
+ { kpidEncrypted, L"Encrypted" },
+ { kpidSplitBefore, L"Split Before" },
+ { kpidSplitAfter, L"Split After" },
+ { kpidDictionarySize, L"Dictionary Size" },
+ { kpidCRC, L"CRC" },
+ { kpidType, L"Type" },
+ { kpidIsAnti, L"Anti" },
+ { kpidMethod, L"Method" },
+ { kpidHostOS, L"Host OS" },
+ { kpidFileSystem, L"File System" },
+ { kpidUser, L"User" },
+ { kpidGroup, L"Group" },
+ { kpidBlock, L"Block" },
+ { kpidComment, L"Comment" },
+ { kpidPosition, L"Position" }
+};
+
+static const char kEmptyAttributeChar = '.';
+static const char kDirectoryAttributeChar = 'D';
+static const char kReadonlyAttributeChar = 'R';
+static const char kHiddenAttributeChar = 'H';
+static const char kSystemAttributeChar = 'S';
+static const char kArchiveAttributeChar = 'A';
+
+static const char *kListing = "Listing archive: ";
+static const wchar_t *kFilesMessage = L"files";
+
+static void GetAttributesString(DWORD wa, bool directory, char *s)
+{
+ s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || directory) ?
+ kDirectoryAttributeChar: kEmptyAttributeChar;
+ s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0)?
+ kReadonlyAttributeChar: kEmptyAttributeChar;
+ s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ?
+ kHiddenAttributeChar: kEmptyAttributeChar;
+ s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ?
+ kSystemAttributeChar: kEmptyAttributeChar;
+ s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ?
+ kArchiveAttributeChar: kEmptyAttributeChar;
+ s[5] = '\0';
+}
+
+enum EAdjustment
+{
+ kLeft,
+ kCenter,
+ kRight
+};
+
+struct CFieldInfo
+{
+ PROPID PropID;
+ UString Name;
+ EAdjustment TitleAdjustment;
+ EAdjustment TextAdjustment;
+ int PrefixSpacesWidth;
+ int Width;
+};
+
+struct CFieldInfoInit
+{
+ PROPID PropID;
+ const wchar_t *Name;
+ EAdjustment TitleAdjustment;
+ EAdjustment TextAdjustment;
+ int PrefixSpacesWidth;
+ int Width;
+};
+
+CFieldInfoInit kStandardFieldTable[] =
+{
+ { kpidLastWriteTime, L" Date Time", kLeft, kLeft, 0, 19 },
+ { kpidAttributes, L"Attr", kRight, kCenter, 1, 5 },
+ { kpidSize, L"Size", kRight, kRight, 1, 12 },
+ { kpidPackedSize, L"Compressed", kRight, kRight, 1, 12 },
+ { kpidPath, L"Name", kLeft, kLeft, 2, 12 }
+};
+
+void PrintSpaces(int numSpaces)
+{
+ for (int i = 0; i < numSpaces; i++)
+ g_StdOut << ' ';
+}
+
+void PrintString(EAdjustment adjustment, int width, const UString &textString)
+{
+ const int numSpaces = width - textString.Length();
+ int numLeftSpaces = 0;
+ switch (adjustment)
+ {
+ case kLeft:
+ numLeftSpaces = 0;
+ break;
+ case kCenter:
+ numLeftSpaces = numSpaces / 2;
+ break;
+ case kRight:
+ numLeftSpaces = numSpaces;
+ break;
+ }
+ PrintSpaces(numLeftSpaces);
+ g_StdOut << textString;
+ PrintSpaces(numSpaces - numLeftSpaces);
+}
+
+class CFieldPrinter
+{
+ CObjectVector<CFieldInfo> _fields;
+public:
+ void Clear() { _fields.Clear(); }
+ void Init(const CFieldInfoInit *standardFieldTable, int numItems);
+ HRESULT Init(IInArchive *archive);
+ void PrintTitle();
+ void PrintTitleLines();
+ HRESULT PrintItemInfo(IInArchive *archive,
+ const UString &defaultItemName,
+ const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
+ UInt32 index,
+ bool techMode);
+ HRESULT PrintSummaryInfo(UInt64 numFiles, const UInt64 *size,
+ const UInt64 *compressedSize);
+};
+
+void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)
+{
+ Clear();
+ for (int i = 0; i < numItems; i++)
+ {
+ CFieldInfo fieldInfo;
+ const CFieldInfoInit &fieldInfoInit = standardFieldTable[i];
+ fieldInfo.PropID = fieldInfoInit.PropID;
+ fieldInfo.Name = fieldInfoInit.Name;
+ fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment;
+ fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment;
+ fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth;
+ fieldInfo.Width = fieldInfoInit.Width;
+ _fields.Add(fieldInfo);
+ }
+}
+
+HRESULT CFieldPrinter::Init(IInArchive *archive)
+{
+ Clear();
+ UInt32 numProps;
+ RINOK(archive->GetNumberOfProperties(&numProps));
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ CMyComBSTR name;
+ PROPID propID;
+ VARTYPE vt;
+ RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt));
+ CFieldInfo fieldInfo;
+ fieldInfo.PropID = propID;
+ if (name != NULL)
+ fieldInfo.Name = name;
+ else
+ {
+ fieldInfo.Name = L"Unknown";
+ for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++)
+ {
+ const CPropIdToName &propIdToName = kPropIdToName[i];
+ if (propIdToName.PropID == propID)
+ {
+ fieldInfo.Name = propIdToName.Name;
+ break;
+ }
+ }
+ }
+ _fields.Add(fieldInfo);
+ }
+ return S_OK;
+}
+
+void CFieldPrinter::PrintTitle()
+{
+ for (int i = 0; i < _fields.Size(); i++)
+ {
+ const CFieldInfo &fieldInfo = _fields[i];
+ PrintSpaces(fieldInfo.PrefixSpacesWidth);
+ PrintString(fieldInfo.TitleAdjustment,
+ ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name);
+ }
+}
+
+void CFieldPrinter::PrintTitleLines()
+{
+ for (int i = 0; i < _fields.Size(); i++)
+ {
+ const CFieldInfo &fieldInfo = _fields[i];
+ PrintSpaces(fieldInfo.PrefixSpacesWidth);
+ for (int i = 0; i < fieldInfo.Width; i++)
+ g_StdOut << '-';
+ }
+}
+
+
+BOOL IsFileTimeZero(CONST FILETIME *lpFileTime)
+{
+ return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0);
+}
+
+static const char *kEmptyTimeString = " ";
+void PrintTime(const NCOM::CPropVariant &propVariant)
+{
+ if (propVariant.vt != VT_FILETIME)
+ throw "incorrect item";
+ if (IsFileTimeZero(&propVariant.filetime))
+ g_StdOut << kEmptyTimeString;
+ else
+ {
+ FILETIME localFileTime;
+ if (!FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime))
+ throw "FileTimeToLocalFileTime error";
+ char s[32];
+ if (ConvertFileTimeToString(localFileTime, s, true, true))
+ g_StdOut << s;
+ else
+ g_StdOut << kEmptyTimeString;
+ }
+}
+
+HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive,
+ const UString &defaultItemName,
+ const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
+ UInt32 index,
+ bool techMode)
+{
+ /*
+ if (techMode)
+ {
+ g_StdOut << "Index = ";
+ g_StdOut << (UInt64)index;
+ g_StdOut << endl;
+ }
+ */
+ for (int i = 0; i < _fields.Size(); i++)
+ {
+ const CFieldInfo &fieldInfo = _fields[i];
+ if (!techMode)
+ PrintSpaces(fieldInfo.PrefixSpacesWidth);
+
+ NCOM::CPropVariant propVariant;
+ RINOK(archive->GetProperty(index, fieldInfo.PropID, &propVariant));
+ if (techMode)
+ {
+ g_StdOut << fieldInfo.Name << " = ";
+ }
+ int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width;
+ if (propVariant.vt == VT_EMPTY)
+ {
+ switch(fieldInfo.PropID)
+ {
+ case kpidPath:
+ propVariant = defaultItemName;
+ break;
+ case kpidLastWriteTime:
+ propVariant = archiveFileInfo.LastWriteTime;
+ break;
+ default:
+ if (techMode)
+ g_StdOut << endl;
+ else
+ PrintSpaces(width);
+ continue;
+ }
+ }
+ if (fieldInfo.PropID == kpidLastWriteTime)
+ {
+ PrintTime(propVariant);
+ }
+ else if (fieldInfo.PropID == kpidAttributes)
+ {
+ if (propVariant.vt != VT_UI4)
+ throw "incorrect item";
+ UInt32 attributes = propVariant.ulVal;
+ bool isFolder;
+ RINOK(IsArchiveItemFolder(archive, index, isFolder));
+ char s[8];
+ GetAttributesString(attributes, isFolder, s);
+ g_StdOut << s;
+ }
+ else if (propVariant.vt == VT_BSTR)
+ {
+ if (techMode)
+ g_StdOut << propVariant.bstrVal;
+ else
+ PrintString(fieldInfo.TextAdjustment, width, propVariant.bstrVal);
+ }
+ else
+ {
+ UString s = ConvertPropertyToString(propVariant, fieldInfo.PropID);
+ if (techMode)
+ g_StdOut << s;
+ else
+ PrintString(fieldInfo.TextAdjustment, width, s);
+ }
+ if (techMode)
+ g_StdOut << endl;
+ }
+ return S_OK;
+}
+
+void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value)
+{
+ wchar_t textString[32] = { 0 };
+ if (value != NULL)
+ ConvertUInt64ToString(*value, textString);
+ PrintString(adjustment, width, textString);
+}
+
+
+HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles,
+ const UInt64 *size, const UInt64 *compressedSize)
+{
+ for (int i = 0; i < _fields.Size(); i++)
+ {
+ const CFieldInfo &fieldInfo = _fields[i];
+ PrintSpaces(fieldInfo.PrefixSpacesWidth);
+ NCOM::CPropVariant propVariant;
+ if (fieldInfo.PropID == kpidSize)
+ PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size);
+ else if (fieldInfo.PropID == kpidPackedSize)
+ PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize);
+ else if (fieldInfo.PropID == kpidPath)
+ {
+ wchar_t textString[32];
+ ConvertUInt64ToString(numFiles, textString);
+ UString temp = textString;
+ temp += L" ";
+ temp += kFilesMessage;
+ PrintString(fieldInfo.TextAdjustment, 0, temp);
+ }
+ else
+ PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L"");
+ }
+ return S_OK;
+}
+
+bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value)
+{
+ NCOM::CPropVariant propVariant;
+ if (archive->GetProperty(index, propID, &propVariant) != S_OK)
+ throw "GetPropertyValue error";
+ if (propVariant.vt == VT_EMPTY)
+ return false;
+ value = ConvertPropVariantToUInt64(propVariant);
+ return true;
+}
+
+HRESULT ListArchives(UStringVector &archivePaths, UStringVector &archivePathsFull,
+ const NWildcard::CCensorNode &wildcardCensor,
+ bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password)
+{
+ CFieldPrinter fieldPrinter;
+ if (!techMode)
+ fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));
+
+ UInt64 numFiles2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;
+ UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;
+ int numErrors = 0;
+ for (int i = 0; i < archivePaths.Size(); i++)
+ {
+ const UString &archiveName = archivePaths[i];
+ NFile::NFind::CFileInfoW archiveFileInfo;
+ if (!NFile::NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory())
+ {
+ g_StdOut << endl << "Error: " << archiveName << " is not archive" << endl;
+ numErrors++;
+ continue;
+ }
+ if (archiveFileInfo.IsDirectory())
+ {
+ g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;
+ numErrors++;
+ continue;
+ }
+
+ CArchiveLink archiveLink;
+
+ COpenCallbackConsole openCallback;
+ openCallback.OutStream = &g_StdOut;
+ openCallback.PasswordIsDefined = passwordEnabled;
+ openCallback.Password = password;
+
+ HRESULT result = MyOpenArchive(archiveName, archiveLink, &openCallback);
+ if (result != S_OK)
+ {
+ g_StdOut << endl << "Error: " << archiveName << " is not supported archive" << endl;
+ numErrors++;
+ continue;
+ }
+
+ for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
+ {
+ int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
+ if (index >= 0 && index > i)
+ {
+ archivePaths.Delete(index);
+ archivePathsFull.Delete(index);
+ }
+ }
+
+ IInArchive *archive = archiveLink.GetArchive();
+ const UString defaultItemName = archiveLink.GetDefaultItemName();
+
+ if (enableHeaders)
+ g_StdOut << endl << kListing << archiveName << endl << endl;
+
+ if (enableHeaders && !techMode)
+ {
+ fieldPrinter.PrintTitle();
+ g_StdOut << endl;
+ fieldPrinter.PrintTitleLines();
+ g_StdOut << endl;
+ }
+
+ if (techMode)
+ {
+ RINOK(fieldPrinter.Init(archive));
+ }
+ UInt64 numFiles = 0, totalPackSize = 0, totalUnPackSize = 0;
+ UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;
+ UInt32 numItems;
+ RINOK(archive->GetNumberOfItems(&numItems));
+ for(UInt32 i = 0; i < numItems; i++)
+ {
+ if (NConsoleClose::TestBreakSignal())
+ return E_ABORT;
+
+ UString filePath;
+ RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath));
+
+ bool isFolder;
+ RINOK(IsArchiveItemFolder(archive, i, isFolder));
+ if (!wildcardCensor.CheckPath(filePath, !isFolder))
+ continue;
+
+ fieldPrinter.PrintItemInfo(archive, defaultItemName, archiveFileInfo, i, techMode);
+
+ UInt64 packSize, unpackSize;
+ if (!GetUInt64Value(archive, i, kpidSize, unpackSize))
+ unpackSize = 0;
+ else
+ totalUnPackSizePointer = &totalUnPackSize;
+ if (!GetUInt64Value(archive, i, kpidPackedSize, packSize))
+ packSize = 0;
+ else
+ totalPackSizePointer = &totalPackSize;
+
+ g_StdOut << endl;
+
+ numFiles++;
+ totalPackSize += packSize;
+ totalUnPackSize += unpackSize;
+ }
+ if (enableHeaders && !techMode)
+ {
+ fieldPrinter.PrintTitleLines();
+ g_StdOut << endl;
+ fieldPrinter.PrintSummaryInfo(numFiles, totalUnPackSizePointer, totalPackSizePointer);
+ g_StdOut << endl;
+ }
+ if (totalPackSizePointer != 0)
+ {
+ totalPackSizePointer2 = &totalPackSize2;
+ totalPackSize2 += totalPackSize;
+ }
+ if (totalUnPackSizePointer != 0)
+ {
+ totalUnPackSizePointer2 = &totalUnPackSize2;
+ totalUnPackSize2 += totalUnPackSize;
+ }
+ numFiles2 += numFiles;
+ }
+ if (enableHeaders && !techMode && archivePaths.Size() > 1)
+ {
+ g_StdOut << endl;
+ fieldPrinter.PrintTitleLines();
+ g_StdOut << endl;
+ fieldPrinter.PrintSummaryInfo(numFiles2, totalUnPackSizePointer2, totalPackSizePointer2);
+ g_StdOut << endl;
+ g_StdOut << "Archives: " << archivePaths.Size() << endl;
+ }
+ if (numErrors > 0)
+ g_StdOut << endl << "Errors: " << numErrors;
+ return S_OK;
+}
diff --git a/CPP/7zip/UI/Console/List.h b/CPP/7zip/UI/Console/List.h
new file mode 100755
index 00000000..201a4128
--- /dev/null
+++ b/CPP/7zip/UI/Console/List.h
@@ -0,0 +1,13 @@
+// List.h
+
+#ifndef __LIST_H
+#define __LIST_H
+
+#include "Common/Wildcard.h"
+
+HRESULT ListArchives(UStringVector &archivePaths, UStringVector &archivePathsFull,
+ const NWildcard::CCensorNode &wildcardCensor,
+ bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password);
+
+#endif
+
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
new file mode 100755
index 00000000..387b8c2a
--- /dev/null
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -0,0 +1,382 @@
+// Main.cpp
+
+#include "StdAfx.h"
+
+#include <io.h>
+
+#include "Common/MyInitGuid.h"
+#include "Common/CommandLineParser.h"
+#include "Common/StdOutStream.h"
+#include "Common/Wildcard.h"
+#include "Common/ListFileUtils.h"
+#include "Common/StringConvert.h"
+#include "Common/StdInStream.h"
+#include "Common/StringToInt.h"
+#include "Common/Exception.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/FileName.h"
+#include "Windows/Defs.h"
+#include "Windows/Error.h"
+// #include "Windows/System.h"
+#ifdef _WIN32
+#include "Windows/MemoryLock.h"
+#endif
+
+#include "../../IPassword.h"
+#include "../../ICoder.h"
+#include "../Common/ArchiverInfo.h"
+#include "../Common/UpdateAction.h"
+#include "../Common/Update.h"
+#include "../Common/Extract.h"
+#include "../Common/ArchiveCommandLine.h"
+#include "../Common/ExitCode.h"
+
+#include "List.h"
+#include "OpenCallbackConsole.h"
+#include "ExtractCallbackConsole.h"
+#include "UpdateCallbackConsole.h"
+
+#include "../../MyVersion.h"
+
+#ifndef EXCLUDE_COM
+#include "Windows/DLL.h"
+#endif
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NCommandLineParser;
+
+HINSTANCE g_hInstance = 0;
+extern CStdOutStream *g_StdStream;
+
+static const char *kCopyrightString = "\n7-Zip"
+#ifdef EXCLUDE_COM
+" (A)"
+#endif
+
+#ifdef UNICODE
+" [NT]"
+#endif
+
+" " MY_VERSION_COPYRIGHT_DATE "\n";
+
+static const char *kHelpString =
+ "\nUsage: 7z"
+#ifdef _NO_CRYPTO
+ "r"
+#elif EXCLUDE_COM
+ "a"
+#endif
+ " <command> [<switches>...] <archive_name> [<file_names>...]\n"
+ " [<@listfiles...>]\n"
+ "\n"
+ "<Commands>\n"
+ " a: Add files to archive\n"
+ " d: Delete files from archive\n"
+ " e: Extract files from archive (without using directory names)\n"
+ " l: List contents of archive\n"
+// " l[a|t][f]: List contents of archive\n"
+// " a - with Additional fields\n"
+// " t - with all fields\n"
+// " f - with Full pathnames\n"
+ " t: Test integrity of archive\n"
+ " u: Update files to archive\n"
+ " x: eXtract files with full paths\n"
+ "<Switches>\n"
+ " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n"
+ " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n"
+ " -bd: Disable percentage indicator\n"
+ " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n"
+ " -m{Parameters}: set compression Method\n"
+ " -o{Directory}: set Output directory\n"
+ " -p{Password}: set Password\n"
+ " -r[-|0]: Recurse subdirectories\n"
+ " -scs{UTF-8 | WIN | DOS}: set charset for list files\n"
+ " -sfx[{name}]: Create SFX archive\n"
+ " -si[{name}]: read data from stdin\n"
+ " -slt: show technical information for l (List) command\n"
+ " -so: write data to stdout\n"
+ " -t{Type}: Set type of archive\n"
+ " -v{Size}[b|k|m|g]: Create volumes\n"
+ " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n"
+ " -w[{path}]: assign Work directory. Empty path means a temporary directory\n"
+ " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n"
+ " -y: assume Yes on all queries\n";
+
+// ---------------------------
+// exception messages
+
+static const char *kProcessArchiveMessage = " archive: ";
+static const char *kEverythingIsOk = "Everything is Ok";
+static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError
+
+static const wchar_t *kDefaultSfxModule = L"7zCon.sfx";
+
+static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code)
+{
+ s << message << endl;
+ throw code;
+}
+
+static void PrintHelpAndExit(CStdOutStream &s) // yyy
+{
+ s << kHelpString;
+ ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError);
+}
+
+#ifndef _WIN32
+static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts)
+{
+ parts.Clear();
+ for(int i = 0; i < numArguments; i++)
+ {
+ UString s = MultiByteToUnicodeString(arguments[i]);
+ parts.Add(s);
+ }
+}
+#endif
+
+static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp)
+{
+ s << kCopyrightString;
+ /*
+ UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
+ s << "System configuration: " << (UInt64)numCPUs << " CPU";
+ if (numCPUs > 1)
+ s << "s";
+ s << "\n";
+ */
+ if (needHelp)
+ s << kHelpString;
+}
+
+int Main2(
+ #ifndef _WIN32
+ int numArguments, const char *arguments[]
+ #endif
+)
+{
+ #ifdef _WIN32
+ SetFileApisToOEM();
+ #endif
+
+ UStringVector commandStrings;
+ #ifdef _WIN32
+ NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
+ #else
+ GetArguments(numArguments, arguments, commandStrings);
+ #endif
+
+ if(commandStrings.Size() == 1)
+ {
+ ShowCopyrightAndHelp(g_StdOut, true);
+ return 0;
+ }
+ commandStrings.Delete(0);
+
+ CArchiveCommandLineOptions options;
+
+ CArchiveCommandLineParser parser;
+
+ parser.Parse1(commandStrings, options);
+
+ if(options.HelpMode)
+ {
+ ShowCopyrightAndHelp(g_StdOut, true);
+ return 0;
+ }
+
+ #ifdef _WIN32
+ if (options.LargePages)
+ NSecurity::EnableLockMemoryPrivilege();
+ #endif
+
+ CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut;
+ g_StdStream = &stdStream;
+
+ if (options.EnableHeaders)
+ ShowCopyrightAndHelp(stdStream, false);
+
+ parser.Parse2(options);
+
+ bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
+ if(isExtractGroupCommand ||
+ options.Command.CommandType == NCommandType::kList)
+ {
+ if(isExtractGroupCommand)
+ {
+ CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
+ CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
+
+ ecs->OutStream = &stdStream;
+ ecs->PasswordIsDefined = options.PasswordEnabled;
+ ecs->Password = options.Password;
+ ecs->Init();
+
+ COpenCallbackConsole openCallback;
+ openCallback.OutStream = &stdStream;
+ openCallback.PasswordIsDefined = options.PasswordEnabled;
+ openCallback.Password = options.Password;
+
+ CExtractOptions eo;
+ eo.StdOutMode = options.StdOutMode;
+ eo.PathMode = options.Command.GetPathMode();
+ eo.TestMode = options.Command.IsTestMode();
+ eo.OverwriteMode = options.OverwriteMode;
+ eo.OutputDir = options.OutputDir;
+ eo.YesToAll = options.YesToAll;
+ #ifdef COMPRESS_MT
+ eo.Properties = options.ExtractProperties;
+ #endif
+ UString errorMessage;
+ HRESULT result = DecompressArchives(
+ options.ArchivePathsSorted,
+ options.ArchivePathsFullSorted,
+ options.WildcardCensor.Pairs.Front().Head,
+ eo, &openCallback, ecs, errorMessage);
+ if (!errorMessage.IsEmpty())
+ {
+ stdStream << endl << "Error: " << errorMessage;
+ if (result == S_OK)
+ result = E_FAIL;
+ }
+
+ if (ecs->NumArchives > 1)
+ {
+ stdStream << endl << endl << "Total:" << endl;
+ stdStream << "Archives: " << ecs->NumArchives << endl;
+ }
+ if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0)
+ {
+ if (ecs->NumArchives > 1)
+ {
+ if (ecs->NumArchiveErrors != 0)
+ stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl;
+ if (ecs->NumFileErrors != 0)
+ stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl;
+ }
+ if (result != S_OK)
+ throw CSystemException(result);
+ return NExitCode::kFatalError;
+ }
+ if (result != S_OK)
+ throw CSystemException(result);
+ }
+ else
+ {
+ HRESULT result = ListArchives(
+ options.ArchivePathsSorted,
+ options.ArchivePathsFullSorted,
+ options.WildcardCensor.Pairs.Front().Head,
+ options.EnableHeaders,
+ options.TechMode,
+ options.PasswordEnabled,
+ options.Password);
+ if (result != S_OK)
+ throw CSystemException(result);
+ }
+ }
+ else if(options.Command.IsFromUpdateGroup())
+ {
+ UString workingDir;
+
+ CUpdateOptions &uo = options.UpdateOptions;
+ if (uo.SfxMode && uo.SfxModule.IsEmpty())
+ uo.SfxModule = kDefaultSfxModule;
+
+ bool passwordIsDefined =
+ options.PasswordEnabled && !options.Password.IsEmpty();
+
+ COpenCallbackConsole openCallback;
+ openCallback.OutStream = &stdStream;
+ openCallback.PasswordIsDefined = passwordIsDefined;
+ openCallback.Password = options.Password;
+
+ CUpdateCallbackConsole callback;
+ callback.EnablePercents = options.EnablePercents;
+ callback.PasswordIsDefined = passwordIsDefined;
+ callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();
+ callback.Password = options.Password;
+ callback.StdOutMode = uo.StdOutMode;
+ callback.Init(&stdStream);
+
+ CUpdateErrorInfo errorInfo;
+
+ HRESULT result = UpdateArchive(options.WildcardCensor, uo,
+ errorInfo, &openCallback, &callback);
+
+ int exitCode = NExitCode::kSuccess;
+ if (callback.CantFindFiles.Size() > 0)
+ {
+ stdStream << endl;
+ stdStream << "WARNINGS for files:" << endl << endl;
+ int numErrors = callback.CantFindFiles.Size();
+ for (int i = 0; i < numErrors; i++)
+ {
+ stdStream << callback.CantFindFiles[i] << " : ";
+ stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl;
+ }
+ stdStream << "----------------" << endl;
+ stdStream << "WARNING: Cannot find " << numErrors << " file";
+ if (numErrors > 1)
+ stdStream << "s";
+ stdStream << endl;
+ exitCode = NExitCode::kWarning;
+ }
+
+ if (result != S_OK)
+ {
+ UString message;
+ if (!errorInfo.Message.IsEmpty())
+ {
+ message += errorInfo.Message;
+ message += L"\n";
+ }
+ if (!errorInfo.FileName.IsEmpty())
+ {
+ message += errorInfo.FileName;
+ message += L"\n";
+ }
+ if (!errorInfo.FileName2.IsEmpty())
+ {
+ message += errorInfo.FileName2;
+ message += L"\n";
+ }
+ if (errorInfo.SystemError != 0)
+ {
+ message += NError::MyFormatMessageW(errorInfo.SystemError);
+ message += L"\n";
+ }
+ if (!message.IsEmpty())
+ stdStream << L"\nError:\n" << message;
+ throw CSystemException(result);
+ }
+ int numErrors = callback.FailedFiles.Size();
+ if (numErrors == 0)
+ {
+ if (callback.CantFindFiles.Size() == 0)
+ stdStream << kEverythingIsOk << endl;
+ }
+ else
+ {
+ stdStream << endl;
+ stdStream << "WARNINGS for files:" << endl << endl;
+ for (int i = 0; i < numErrors; i++)
+ {
+ stdStream << callback.FailedFiles[i] << " : ";
+ stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl;
+ }
+ stdStream << "----------------" << endl;
+ stdStream << "WARNING: Cannot open " << numErrors << " file";
+ if (numErrors > 1)
+ stdStream << "s";
+ stdStream << endl;
+ exitCode = NExitCode::kWarning;
+ }
+ return exitCode;
+ }
+ else
+ PrintHelpAndExit(stdStream);
+ return 0;
+}
diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp
new file mode 100755
index 00000000..4bdf813a
--- /dev/null
+++ b/CPP/7zip/UI/Console/MainAr.cpp
@@ -0,0 +1,169 @@
+// MainAr.cpp
+
+#include "StdAfx.h"
+
+// #include <locale.h>
+
+#include "Windows/Error.h"
+
+#include "Common/StdOutStream.h"
+#include "Common/NewHandler.h"
+#include "Common/Exception.h"
+#include "Common/StringConvert.h"
+#ifdef _WIN32
+#include "Common/Alloc.h"
+#endif
+
+#include "../Common/ExitCode.h"
+#include "../Common/ArchiveCommandLine.h"
+#include "ConsoleClose.h"
+
+#ifdef CRC_GENERATE_TABLE
+extern "C"
+{
+ #include "../../../../C/7zCrc.h"
+}
+#endif
+
+using namespace NWindows;
+
+CStdOutStream *g_StdStream = 0;
+
+#ifndef _UNICODE
+bool g_IsNT = false;
+#endif
+
+extern int Main2(
+ #ifndef _WIN32
+ int numArguments, const char *arguments[]
+ #endif
+);
+
+static const char *kExceptionErrorMessage = "\n\nError:\n";
+static const char *kUserBreak = "\nBreak signaled\n";
+
+static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n";
+static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n";
+static const char *kInternalExceptionMessage = "\n\nInternal Error #";
+
+static inline bool IsItWindowsNT()
+{
+ OSVERSIONINFO versionInfo;
+ versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+ if (!::GetVersionEx(&versionInfo))
+ return false;
+ return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+
+int
+#ifdef _MSC_VER
+__cdecl
+#endif
+main
+(
+#ifndef _WIN32
+int numArguments, const char *arguments[]
+#endif
+)
+{
+ #ifdef CRC_GENERATE_TABLE
+ CrcGenerateTable();
+ #endif
+ g_StdStream = &g_StdOut;
+ #ifdef _UNICODE
+ if (!IsItWindowsNT())
+ {
+ (*g_StdStream) << "This program requires Windows NT/2000/XP/2003";
+ return NExitCode::kFatalError;
+ }
+ #else
+ g_IsNT = IsItWindowsNT();
+ #endif
+
+ #ifdef _WIN32
+ SetLargePageSize();
+ #endif
+
+ // setlocale(LC_COLLATE, ".OCP");
+ NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
+ int res = 0;
+ try
+ {
+ res = Main2(
+#ifndef _WIN32
+ numArguments, arguments
+#endif
+ );
+ }
+ catch(const CNewException &)
+ {
+ (*g_StdStream) << kMemoryExceptionMessage;
+ return (NExitCode::kMemoryError);
+ }
+ catch(const NConsoleClose::CCtrlBreakException &)
+ {
+ (*g_StdStream) << endl << kUserBreak;
+ return (NExitCode::kUserBreak);
+ }
+ catch(const CArchiveCommandLineException &e)
+ {
+ (*g_StdStream) << kExceptionErrorMessage << e << endl;
+ return (NExitCode::kUserError);
+ }
+ catch(const CSystemException &systemError)
+ {
+ if (systemError.ErrorCode == E_OUTOFMEMORY)
+ {
+ (*g_StdStream) << kMemoryExceptionMessage;
+ return (NExitCode::kMemoryError);
+ }
+ if (systemError.ErrorCode == E_ABORT)
+ {
+ (*g_StdStream) << endl << kUserBreak;
+ return (NExitCode::kUserBreak);
+ }
+ UString message;
+ NError::MyFormatMessage(systemError.ErrorCode, message);
+ (*g_StdStream) << endl << endl << "System error:" << endl <<
+ message << endl;
+ return (NExitCode::kFatalError);
+ }
+ catch(NExitCode::EEnum &exitCode)
+ {
+ (*g_StdStream) << kInternalExceptionMessage << exitCode << endl;
+ return (exitCode);
+ }
+ /*
+ catch(const NExitCode::CMultipleErrors &multipleErrors)
+ {
+ (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl;
+ return (NExitCode::kFatalError);
+ }
+ */
+ catch(const UString &s)
+ {
+ (*g_StdStream) << kExceptionErrorMessage << s << endl;
+ return (NExitCode::kFatalError);
+ }
+ catch(const AString &s)
+ {
+ (*g_StdStream) << kExceptionErrorMessage << s << endl;
+ return (NExitCode::kFatalError);
+ }
+ catch(const char *s)
+ {
+ (*g_StdStream) << kExceptionErrorMessage << s << endl;
+ return (NExitCode::kFatalError);
+ }
+ catch(int t)
+ {
+ (*g_StdStream) << kInternalExceptionMessage << t << endl;
+ return (NExitCode::kFatalError);
+ }
+ catch(...)
+ {
+ (*g_StdStream) << kUnknownExceptionMessage;
+ return (NExitCode::kFatalError);
+ }
+ return res;
+}
diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
new file mode 100755
index 00000000..06ff165f
--- /dev/null
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
@@ -0,0 +1,58 @@
+// OpenCallbackConsole.cpp
+
+#include "StdAfx.h"
+
+#include "OpenCallbackConsole.h"
+
+#include "ConsoleClose.h"
+#include "UserInputUtils.h"
+
+HRESULT COpenCallbackConsole::CheckBreak()
+{
+ if (NConsoleClose::TestBreakSignal())
+ return E_ABORT;
+ return S_OK;
+}
+
+HRESULT COpenCallbackConsole::SetTotal(const UInt64 *, const UInt64 *)
+{
+ return CheckBreak();
+}
+
+HRESULT COpenCallbackConsole::SetCompleted(const UInt64 *, const UInt64 *)
+{
+ return CheckBreak();
+}
+
+HRESULT COpenCallbackConsole::CryptoGetTextPassword(BSTR *password)
+{
+ PasswordWasAsked = true;
+ RINOK(CheckBreak());
+ if (!PasswordIsDefined)
+ {
+ Password = GetPassword(OutStream);
+ PasswordIsDefined = true;
+ }
+ CMyComBSTR temp(Password);
+ *password = temp.Detach();
+ return S_OK;
+}
+
+HRESULT COpenCallbackConsole::GetPasswordIfAny(UString &password)
+{
+ if (PasswordIsDefined)
+ password = Password;
+ return S_OK;
+}
+
+bool COpenCallbackConsole::WasPasswordAsked()
+{
+ return PasswordWasAsked;
+}
+
+void COpenCallbackConsole::ClearPasswordWasAskedFlag()
+{
+ PasswordWasAsked = false;
+}
+
+
diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h
new file mode 100755
index 00000000..db0e9bd8
--- /dev/null
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h
@@ -0,0 +1,27 @@
+// OpenCallbackConsole.h
+
+#ifndef __OPENCALLBACKCONSOLE_H
+#define __OPENCALLBACKCONSOLE_H
+
+#include "Common/StdOutStream.h"
+#include "../Common/ArchiveOpenCallback.h"
+
+class COpenCallbackConsole: public IOpenCallbackUI
+{
+public:
+ HRESULT CheckBreak();
+ HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes);
+ HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes);
+ HRESULT CryptoGetTextPassword(BSTR *password);
+ HRESULT GetPasswordIfAny(UString &password);
+ bool WasPasswordAsked();
+ void ClearPasswordWasAskedFlag();
+
+ CStdOutStream *OutStream;
+ bool PasswordIsDefined;
+ UString Password;
+ bool PasswordWasAsked;
+ COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {}
+};
+
+#endif
diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp
new file mode 100755
index 00000000..ec87b5d4
--- /dev/null
+++ b/CPP/7zip/UI/Console/PercentPrinter.cpp
@@ -0,0 +1,90 @@
+// PercentPrinter.cpp
+
+#include "StdAfx.h"
+
+#include "Common/IntToString.h"
+#include "Common/String.h"
+
+#include "PercentPrinter.h"
+
+const int kPaddingSize = 2;
+const int kPercentsSize = 4;
+const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize;
+
+static void ClearPrev(char *p, int num)
+{
+ int i;
+ for (i = 0; i < num; i++) *p++ = '\b';
+ for (i = 0; i < num; i++) *p++ = ' ';
+ for (i = 0; i < num; i++) *p++ = '\b';
+ *p = '\0';
+}
+
+void CPercentPrinter::ClosePrint()
+{
+ if (m_NumExtraChars == 0)
+ return;
+ char s[kMaxExtraSize * 3 + 1];
+ ClearPrev(s, m_NumExtraChars);
+ (*OutStream) << s;
+ m_NumExtraChars = 0;
+}
+
+void CPercentPrinter::PrintString(const char *s)
+{
+ ClosePrint();
+ (*OutStream) << s;
+}
+
+void CPercentPrinter::PrintString(const wchar_t *s)
+{
+ ClosePrint();
+ (*OutStream) << s;
+}
+
+void CPercentPrinter::PrintNewLine()
+{
+ ClosePrint();
+ (*OutStream) << "\n";
+}
+
+void CPercentPrinter::RePrintRatio()
+{
+ char s[32];
+ ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s);
+ int size = (int)strlen(s);
+ s[size++] = '%';
+ s[size] = '\0';
+
+ int extraSize = kPaddingSize + MyMax(size, kPercentsSize);
+ if (extraSize < m_NumExtraChars)
+ extraSize = m_NumExtraChars;
+
+ char fullString[kMaxExtraSize * 3];
+ char *p = fullString;
+ int i;
+ if (m_NumExtraChars == 0)
+ {
+ for (i = 0; i < extraSize; i++)
+ *p++ = ' ';
+ m_NumExtraChars = extraSize;
+ }
+
+ for (i = 0; i < m_NumExtraChars; i++)
+ *p++ = '\b';
+ m_NumExtraChars = extraSize;
+ for (; size < m_NumExtraChars; size++)
+ *p++ = ' ';
+ strcpy(p, s);
+ (*OutStream) << fullString;
+ OutStream->Flush();
+ m_PrevValue = m_CurValue;
+}
+
+void CPercentPrinter::PrintRatio()
+{
+ if (m_CurValue < m_PrevValue + m_MinStepSize &&
+ m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0)
+ return;
+ RePrintRatio();
+}
diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h
new file mode 100755
index 00000000..e8b40916
--- /dev/null
+++ b/CPP/7zip/UI/Console/PercentPrinter.h
@@ -0,0 +1,31 @@
+// PercentPrinter.h
+
+#ifndef __PERCENTPRINTER_H
+#define __PERCENTPRINTER_H
+
+#include "Common/Types.h"
+#include "Common/StdOutStream.h"
+
+class CPercentPrinter
+{
+ UInt64 m_MinStepSize;
+ UInt64 m_PrevValue;
+ UInt64 m_CurValue;
+ UInt64 m_Total;
+ int m_NumExtraChars;
+public:
+ CStdOutStream *OutStream;
+
+ CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize),
+ m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {}
+ void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; }
+ void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; }
+ void PrintString(const char *s);
+ void PrintString(const wchar_t *s);
+ void PrintNewLine();
+ void ClosePrint();
+ void RePrintRatio();
+ void PrintRatio();
+};
+
+#endif
diff --git a/CPP/7zip/UI/Console/StdAfx.cpp b/CPP/7zip/UI/Console/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/UI/Console/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/UI/Console/StdAfx.h b/CPP/7zip/UI/Console/StdAfx.h
new file mode 100755
index 00000000..8531cc9c
--- /dev/null
+++ b/CPP/7zip/UI/Console/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
new file mode 100755
index 00000000..5cbc11c0
--- /dev/null
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
@@ -0,0 +1,196 @@
+// UpdateCallbackConsole.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateCallbackConsole.h"
+
+#include "Windows/Error.h"
+#ifdef COMPRESS_MT
+#include "Windows/Synchronization.h"
+#endif
+
+#include "ConsoleClose.h"
+#include "UserInputUtils.h"
+
+using namespace NWindows;
+
+#ifdef COMPRESS_MT
+static NSynchronization::CCriticalSection g_CriticalSection;
+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
+#else
+#define MT_LOCK
+#endif
+
+static const wchar_t *kEmptyFileAlias = L"[Content]";
+
+static const char *kCreatingArchiveMessage = "Creating archive ";
+static const char *kUpdatingArchiveMessage = "Updating archive ";
+static const char *kScanningMessage = "Scanning";
+static const char *kNoFilesScannedMessage = "No files scanned";
+static const char *kTotalFilesAddedMessage = "Total files added to archive: ";
+
+
+HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result)
+{
+ (*OutStream) << endl;
+ if (result != S_OK)
+ (*OutStream) << "Error: " << name << " is not supported archive" << endl;
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::StartScanning()
+{
+ (*OutStream) << kScanningMessage;
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)
+{
+ CantFindFiles.Add(name);
+ CantFindCodes.Add(systemError);
+ // m_PercentPrinter.ClosePrint();
+ if (!m_WarningsMode)
+ {
+ (*OutStream) << endl << endl;
+ m_PercentPrinter.PrintNewLine();
+ m_WarningsMode = true;
+ }
+ m_PercentPrinter.PrintString(name);
+ m_PercentPrinter.PrintString(": WARNING: ");
+ m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));
+ m_PercentPrinter.PrintNewLine();
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::FinishScanning()
+{
+ (*OutStream) << endl << endl;
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
+{
+ if(updating)
+ (*OutStream) << kUpdatingArchiveMessage;
+ else
+ (*OutStream) << kCreatingArchiveMessage;
+ if (name != 0)
+ (*OutStream) << name;
+ else
+ (*OutStream) << "StdOut";
+ (*OutStream) << endl << endl;
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::FinishArchive()
+{
+ (*OutStream) << endl;
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::CheckBreak()
+{
+ if (NConsoleClose::TestBreakSignal())
+ return E_ABORT;
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::Finilize()
+{
+ MT_LOCK
+ if (m_NeedBeClosed)
+ {
+ if (EnablePercents)
+ {
+ m_PercentPrinter.ClosePrint();
+ }
+ if (!StdOutMode && m_NeedNewLine)
+ {
+ m_PercentPrinter.PrintNewLine();
+ m_NeedNewLine = false;
+ }
+ m_NeedBeClosed = false;
+ }
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
+{
+ MT_LOCK
+ if (EnablePercents)
+ m_PercentPrinter.SetTotal(size);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
+{
+ MT_LOCK
+ if (completeValue != NULL)
+ {
+ if (EnablePercents)
+ {
+ m_PercentPrinter.SetRatio(*completeValue);
+ m_PercentPrinter.PrintRatio();
+ m_NeedBeClosed = true;
+ }
+ }
+ if (NConsoleClose::TestBreakSignal())
+ return E_ABORT;
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti)
+{
+ MT_LOCK
+ if (StdOutMode)
+ return S_OK;
+ if(isAnti)
+ m_PercentPrinter.PrintString("Anti item ");
+ else
+ m_PercentPrinter.PrintString("Compressing ");
+ if (name[0] == 0)
+ name = kEmptyFileAlias;
+ m_PercentPrinter.PrintString(name);
+ if (EnablePercents)
+ m_PercentPrinter.RePrintRatio();
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError)
+{
+ MT_LOCK
+ FailedCodes.Add(systemError);
+ FailedFiles.Add(name);
+ // if (systemError == ERROR_SHARING_VIOLATION)
+ {
+ m_PercentPrinter.ClosePrint();
+ m_PercentPrinter.PrintNewLine();
+ m_PercentPrinter.PrintString("WARNING: ");
+ m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));
+ return S_FALSE;
+ }
+ // return systemError;
+}
+
+HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 )
+{
+ m_NeedBeClosed = true;
+ m_NeedNewLine = true;
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
+{
+ if (!PasswordIsDefined)
+ {
+ if (AskPassword)
+ {
+ Password = GetPassword(OutStream);
+ PasswordIsDefined = true;
+ }
+ }
+ *passwordIsDefined = BoolToInt(PasswordIsDefined);
+ CMyComBSTR tempName(Password);
+ *password = tempName.Detach();
+ return S_OK;
+}
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
new file mode 100755
index 00000000..2fcb891b
--- /dev/null
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
@@ -0,0 +1,75 @@
+// UpdateCallbackConsole.h
+
+#ifndef __UPDATECALLBACKCONSOLE_H
+#define __UPDATECALLBACKCONSOLE_H
+
+#include "Common/String.h"
+#include "Common/StdOutStream.h"
+#include "PercentPrinter.h"
+#include "../Common/Update.h"
+
+class CUpdateCallbackConsole: public IUpdateCallbackUI2
+{
+ CPercentPrinter m_PercentPrinter;
+ bool m_NeedBeClosed;
+ bool m_NeedNewLine;
+
+ bool m_WarningsMode;
+
+ CStdOutStream *OutStream;
+public:
+ bool EnablePercents;
+ bool StdOutMode;
+
+ bool PasswordIsDefined;
+ UString Password;
+ bool AskPassword;
+
+
+ CUpdateCallbackConsole():
+ m_PercentPrinter(1 << 16),
+ PasswordIsDefined(false),
+ AskPassword(false),
+ StdOutMode(false),
+ EnablePercents(true),
+ m_WarningsMode(false)
+ {}
+
+ ~CUpdateCallbackConsole() { Finilize(); }
+ void Init(CStdOutStream *outStream)
+ {
+ m_NeedBeClosed = false;
+ m_NeedNewLine = false;
+ FailedFiles.Clear();
+ FailedCodes.Clear();
+ OutStream = outStream;
+ m_PercentPrinter.OutStream = outStream;
+ }
+
+ HRESULT OpenResult(const wchar_t *name, HRESULT result);
+
+ HRESULT StartScanning();
+ HRESULT CanNotFindError(const wchar_t *name, DWORD systemError);
+ HRESULT FinishScanning();
+
+ HRESULT StartArchive(const wchar_t *name, bool updating);
+ HRESULT FinishArchive();
+
+ HRESULT CheckBreak();
+ HRESULT Finilize();
+ HRESULT SetTotal(UInt64 size);
+ HRESULT SetCompleted(const UInt64 *completeValue);
+
+ HRESULT GetStream(const wchar_t *name, bool isAnti);
+ HRESULT OpenFileError(const wchar_t *name, DWORD systemError);
+ HRESULT SetOperationResult(Int32 operationResult);
+ HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password);
+
+ UStringVector FailedFiles;
+ CRecordVector<HRESULT> FailedCodes;
+
+ UStringVector CantFindFiles;
+ CRecordVector<HRESULT> CantFindCodes;
+};
+
+#endif
diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp
new file mode 100755
index 00000000..164af99c
--- /dev/null
+++ b/CPP/7zip/UI/Console/UserInputUtils.cpp
@@ -0,0 +1,58 @@
+// UserInputUtils.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StdInStream.h"
+#include "Common/StringConvert.h"
+
+#include "UserInputUtils.h"
+
+static const char kYes = 'Y';
+static const char kNo = 'N';
+static const char kYesAll = 'A';
+static const char kNoAll = 'S';
+static const char kAutoRename = 'U';
+static const char kQuit = 'Q';
+
+static const char *kFirstQuestionMessage = "?\n";
+static const char *kHelpQuestionMessage =
+ "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename / (Q)uit? ";
+
+// return true if pressed Quite;
+// in: anAll
+// out: anAll, anYes;
+
+NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
+{
+ (*outStream) << kFirstQuestionMessage;
+ for(;;)
+ {
+ (*outStream) << kHelpQuestionMessage;
+ AString scannedString = g_StdIn.ScanStringUntilNewLine();
+ scannedString.Trim();
+ if(!scannedString.IsEmpty())
+ switch(::MyCharUpper(scannedString[0]))
+ {
+ case kYes:
+ return NUserAnswerMode::kYes;
+ case kNo:
+ return NUserAnswerMode::kNo;
+ case kYesAll:
+ return NUserAnswerMode::kYesAll;
+ case kNoAll:
+ return NUserAnswerMode::kNoAll;
+ case kAutoRename:
+ return NUserAnswerMode::kAutoRename;
+ case kQuit:
+ return NUserAnswerMode::kQuit;
+ }
+ }
+}
+
+UString GetPassword(CStdOutStream *outStream)
+{
+ (*outStream) << "\nEnter password:";
+ outStream->Flush();
+ AString oemPassword = g_StdIn.ScanStringUntilNewLine();
+ return MultiByteToUnicodeString(oemPassword, CP_OEMCP);
+}
diff --git a/CPP/7zip/UI/Console/UserInputUtils.h b/CPP/7zip/UI/Console/UserInputUtils.h
new file mode 100755
index 00000000..75c85ee6
--- /dev/null
+++ b/CPP/7zip/UI/Console/UserInputUtils.h
@@ -0,0 +1,24 @@
+// UserInputUtils.h
+
+#ifndef __USERINPUTUTILS_H
+#define __USERINPUTUTILS_H
+
+#include "Common/StdOutStream.h"
+
+namespace NUserAnswerMode {
+
+enum EEnum
+{
+ kYes,
+ kNo,
+ kYesAll,
+ kNoAll,
+ kAutoRename,
+ kQuit,
+};
+}
+
+NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);
+UString GetPassword(CStdOutStream *outStream);
+
+#endif
diff --git a/CPP/7zip/UI/Console/afxres.h b/CPP/7zip/UI/Console/afxres.h
new file mode 100755
index 00000000..c2fadd4a
--- /dev/null
+++ b/CPP/7zip/UI/Console/afxres.h
@@ -0,0 +1 @@
+#include <winresrc.h>
diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile
new file mode 100755
index 00000000..54e83ea1
--- /dev/null
+++ b/CPP/7zip/UI/Console/makefile
@@ -0,0 +1,93 @@
+PROG = 7z.exe
+LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib
+CFLAGS = $(CFLAGS) -I ../../../ -DCOMPRESS_MT -DWIN_LONG_PATH
+
+CONSOLE_OBJS = \
+ $O\ConsoleClose.obj \
+ $O\ExtractCallbackConsole.obj \
+ $O\List.obj \
+ $O\Main.obj \
+ $O\MainAr.obj \
+ $O\OpenCallbackConsole.obj \
+ $O\PercentPrinter.obj \
+ $O\UpdateCallbackConsole.obj \
+ $O\UserInputUtils.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\CommandLineParser.obj \
+ $O\IntToString.obj \
+ $O\ListFileUtils.obj \
+ $O\NewHandler.obj \
+ $O\StdInStream.obj \
+ $O\StdOutStream.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\UTFConvert.obj \
+ $O\Vector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\Error.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileName.obj \
+ $O\MemoryLock.obj \
+ $O\PropVariant.obj \
+ $O\PropVariantConversions.obj \
+ $O\Registry.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\FilePathAutoRename.obj \
+ $O\FileStreams.obj \
+ $O\StreamUtils.obj \
+
+UI_COMMON_OBJS = \
+ $O\ArchiveCommandLine.obj \
+ $O\ArchiveExtractCallback.obj \
+ $O\ArchiveOpenCallback.obj \
+ $O\ArchiverInfo.obj \
+ $O\DefaultName.obj \
+ $O\EnumDirItems.obj \
+ $O\Extract.obj \
+ $O\ExtractingFilePath.obj \
+ $O\OpenArchive.obj \
+ $O\PropIDUtils.obj \
+ $O\SetProperties.obj \
+ $O\SortUtils.obj \
+ $O\TempFiles.obj \
+ $O\Update.obj \
+ $O\UpdateAction.obj \
+ $O\UpdateCallback.obj \
+ $O\UpdatePair.obj \
+ $O\UpdateProduce.obj \
+ $O\WorkDir.obj \
+
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(CONSOLE_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(UI_COMMON_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(CONSOLE_OBJS): $(*B).cpp
+ $(COMPL)
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+ $(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+ $(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+ $(COMPL)
+$(UI_COMMON_OBJS): ../Common/$(*B).cpp
+ $(COMPL)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/UI/Console/resource.rc b/CPP/7zip/UI/Console/resource.rc
new file mode 100755
index 00000000..6e09bb96
--- /dev/null
+++ b/CPP/7zip/UI/Console/resource.rc
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_APP("7-Zip Console", "7z")
diff --git a/CPP/7zip/UI/Explorer/7-zip.dll.manifest b/CPP/7zip/UI/Explorer/7-zip.dll.manifest
new file mode 100755
index 00000000..cba1c5df
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/7-zip.dll.manifest
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.7-zip" type="win32"/><description>7-Zip Extension.</description><dependency> <dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly></dependency></assembly>
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp
new file mode 100755
index 00000000..fd40add5
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp
@@ -0,0 +1,682 @@
+// ContextMenu.cpp
+
+#include "StdAfx.h"
+
+#include "ContextMenu.h"
+
+#include "Common/StringConvert.h"
+#include "Common/MyCom.h"
+
+#include "Windows/Shell.h"
+#include "Windows/Memory.h"
+#include "Windows/COM.h"
+#include "Windows/FileFind.h"
+#include "Windows/FileDir.h"
+#include "Windows/FileName.h"
+#include "Windows/Thread.h"
+#include "Windows/Window.h"
+
+#include "Windows/Menu.h"
+#include "Windows/ResourceString.h"
+
+#include "../../FileManager/FormatUtils.h"
+#include "../../FileManager/ProgramLocation.h"
+
+#include "../Common/ZipRegistry.h"
+#include "../Common/ArchiveName.h"
+
+#ifdef LANG
+#include "../../FileManager/LangUtils.h"
+#endif
+
+#include "resource.h"
+#include "ContextMenuFlags.h"
+
+// #include "ExtractEngine.h"
+// #include "TestEngine.h"
+// #include "CompressEngine.h"
+#include "MyMessages.h"
+
+#include "../Resource/Extract/resource.h"
+#include "../Common/CompressCall.h"
+
+using namespace NWindows;
+
+static LPCTSTR kFileClassIDString = TEXT("SevenZip");
+
+///////////////////////////////
+// IShellExtInit
+
+extern LONG g_DllRefCount;
+
+CZipContextMenu::CZipContextMenu() { InterlockedIncrement(&g_DllRefCount); }
+CZipContextMenu::~CZipContextMenu() { InterlockedDecrement(&g_DllRefCount); }
+
+HRESULT CZipContextMenu::GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames)
+{
+ fileNames.Clear();
+ if(dataObject == NULL)
+ return E_FAIL;
+ FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+ NCOM::CStgMedium stgMedium;
+ HRESULT result = dataObject->GetData(&fmte, &stgMedium);
+ if (result != S_OK)
+ return result;
+ stgMedium._mustBeReleased = true;
+
+ NShell::CDrop drop(false);
+ NMemory::CGlobalLock globalLock(stgMedium->hGlobal);
+ drop.Attach((HDROP)globalLock.GetPointer());
+ drop.QueryFileNames(fileNames);
+
+ return S_OK;
+}
+
+STDMETHODIMP CZipContextMenu::Initialize(LPCITEMIDLIST pidlFolder,
+ LPDATAOBJECT dataObject, HKEY /* hkeyProgID */)
+{
+ // OutputDebugString(TEXT("::Initialize\r\n"));
+ _dropMode = false;
+ _dropPath.Empty();
+ if (pidlFolder != 0)
+ {
+ if (NShell::GetPathFromIDList(pidlFolder, _dropPath))
+ {
+ // OutputDebugString(path);
+ // OutputDebugString(TEXT("\r\n"));
+ NFile::NName::NormalizeDirPathPrefix(_dropPath);
+ _dropMode = !_dropPath.IsEmpty();
+ }
+ else
+ _dropPath.Empty();
+ }
+
+ /*
+ m_IsFolder = false;
+ if (pidlFolder == 0)
+ */
+ // pidlFolder is NULL :(
+ return GetFileNames(dataObject, _fileNames);
+}
+
+STDMETHODIMP CZipContextMenu::InitContextMenu(const wchar_t * /* folder */,
+ const wchar_t **names, UINT32 numFiles)
+{
+ _fileNames.Clear();
+ for (UINT32 i = 0; i < numFiles; i++)
+ _fileNames.Add(names[i]);
+ _dropMode = false;
+ return S_OK;
+}
+
+
+/////////////////////////////
+// IContextMenu
+
+static LPCWSTR kMainVerb = L"SevenZip";
+
+/*
+static LPCTSTR kOpenVerb = TEXT("SevenOpen");
+static LPCTSTR kExtractVerb = TEXT("SevenExtract");
+static LPCTSTR kExtractHereVerb = TEXT("SevenExtractHere");
+static LPCTSTR kExtractToVerb = TEXT("SevenExtractTo");
+static LPCTSTR kTestVerb = TEXT("SevenTest");
+static LPCTSTR kCompressVerb = TEXT("SevenCompress");
+static LPCTSTR kCompressToVerb = TEXT("SevenCompressTo");
+static LPCTSTR kCompressEmailVerb = TEXT("SevenCompressEmail");
+static LPCTSTR kCompressToEmailVerb = TEXT("SevenCompressToEmail");
+*/
+
+struct CContextMenuCommand
+{
+ UINT32 flag;
+ CZipContextMenu::ECommandInternalID CommandInternalID;
+ LPCWSTR Verb;
+ UINT ResourceID;
+ UINT ResourceHelpID;
+ UINT32 LangID;
+};
+
+static CContextMenuCommand g_Commands[] =
+{
+ {
+ NContextMenuFlags::kOpen,
+ CZipContextMenu::kOpen,
+ L"Open",
+ IDS_CONTEXT_OPEN,
+ IDS_CONTEXT_OPEN_HELP,
+ 0x02000103
+ },
+ {
+ NContextMenuFlags::kExtract,
+ CZipContextMenu::kExtract,
+ L"Extract",
+ IDS_CONTEXT_EXTRACT,
+ IDS_CONTEXT_EXTRACT_HELP,
+ 0x02000105
+ },
+ {
+ NContextMenuFlags::kExtractHere,
+ CZipContextMenu::kExtractHere,
+ L"ExtractHere",
+ IDS_CONTEXT_EXTRACT_HERE,
+ IDS_CONTEXT_EXTRACT_HERE_HELP,
+ 0x0200010B
+ },
+ {
+ NContextMenuFlags::kExtractTo,
+ CZipContextMenu::kExtractTo,
+ L"ExtractTo",
+ IDS_CONTEXT_EXTRACT_TO,
+ IDS_CONTEXT_EXTRACT_TO_HELP,
+ 0x0200010D
+ },
+ {
+ NContextMenuFlags::kTest,
+ CZipContextMenu::kTest,
+ L"Test",
+ IDS_CONTEXT_TEST,
+ IDS_CONTEXT_TEST_HELP,
+ 0x02000109
+ },
+ {
+ NContextMenuFlags::kCompress,
+ CZipContextMenu::kCompress,
+ L"Compress",
+ IDS_CONTEXT_COMPRESS,
+ IDS_CONTEXT_COMPRESS_HELP,
+ 0x02000107,
+ },
+ {
+ NContextMenuFlags::kCompressEmail,
+ CZipContextMenu::kCompressEmail,
+ L"CompressEmail",
+ IDS_CONTEXT_COMPRESS_EMAIL,
+ IDS_CONTEXT_COMPRESS_EMAIL_HELP,
+ 0x02000111
+ },
+ {
+ NContextMenuFlags::kCompressTo7z,
+ CZipContextMenu::kCompressTo7z,
+ L"CompressTo7z",
+ IDS_CONTEXT_COMPRESS_TO,
+ IDS_CONTEXT_COMPRESS_TO_HELP,
+ 0x0200010F
+ },
+ {
+ NContextMenuFlags::kCompressTo7zEmail,
+ CZipContextMenu::kCompressTo7zEmail,
+ L"CompressTo7zEmail",
+ IDS_CONTEXT_COMPRESS_TO_EMAIL,
+ IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP,
+ 0x02000113
+ },
+ {
+ NContextMenuFlags::kCompressToZip,
+ CZipContextMenu::kCompressToZip,
+ L"CompressToZip",
+ IDS_CONTEXT_COMPRESS_TO,
+ IDS_CONTEXT_COMPRESS_TO_HELP,
+ 0x0200010F
+ },
+ {
+ NContextMenuFlags::kCompressToZipEmail,
+ CZipContextMenu::kCompressToZipEmail,
+ L"CompressToZipEmail",
+ IDS_CONTEXT_COMPRESS_TO_EMAIL,
+ IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP,
+ 0x02000113
+ }
+};
+
+int FindCommand(CZipContextMenu::ECommandInternalID &id)
+{
+ for (int i = 0; i < sizeof(g_Commands) / sizeof(g_Commands[0]); i++)
+ if (g_Commands[i].CommandInternalID == id)
+ return i;
+ return -1;
+}
+
+void CZipContextMenu::FillCommand(ECommandInternalID id,
+ UString &mainString, CCommandMapItem &commandMapItem)
+{
+ int i = FindCommand(id);
+ if (i < 0)
+ return;
+ const CContextMenuCommand &command = g_Commands[i];
+ commandMapItem.CommandInternalID = command.CommandInternalID;
+ commandMapItem.Verb = (UString)kMainVerb + (UString)command.Verb;
+ commandMapItem.HelpString = LangString(command.ResourceHelpID, command.LangID + 1);
+ mainString = LangString(command.ResourceID, command.LangID);
+}
+
+static bool MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s)
+{
+ CMenuItem menuItem;
+ menuItem.fType = MFT_STRING;
+ menuItem.fMask = MIIM_TYPE | MIIM_ID;
+ menuItem.wID = id;
+ menuItem.StringValue = s;
+ return menu.InsertItem(pos, true, menuItem);
+}
+
+static UString GetSubFolderNameForExtract(const UString &archiveName)
+{
+ int dotPos = archiveName.ReverseFind(L'.');
+ if (dotPos < 0)
+ return archiveName + UString(L"~");
+ UString res = archiveName.Left(dotPos);
+ res.TrimRight();
+ return res;
+}
+
+static UString GetReducedString(const UString &s)
+{
+ const int kMaxSize = 64;
+ if (s.Length() < kMaxSize)
+ return s;
+ const int kFirstPartSize = kMaxSize / 2;
+ return s.Left(kFirstPartSize) + UString(L" ... ") + s.Right(kMaxSize - kFirstPartSize);
+}
+
+STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
+ UINT commandIDFirst, UINT commandIDLast, UINT flags)
+{
+ LoadLangOneTime();
+ if(_fileNames.Size() == 0)
+ return E_FAIL;
+ UINT currentCommandID = commandIDFirst;
+ if ((flags & 0x000F) != CMF_NORMAL &&
+ (flags & CMF_VERBSONLY) == 0 &&
+ (flags & CMF_EXPLORE) == 0)
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID);
+
+ _commandMap.Clear();
+
+ CMenu popupMenu;
+ CMenuDestroyer menuDestroyer;
+
+ bool cascadedMenu = ReadCascadedMenu();
+ MENUITEMINFO menuItem;
+ UINT subIndex = indexMenu;
+ if (cascadedMenu)
+ {
+ CCommandMapItem commandMapItem;
+ if(!popupMenu.CreatePopup())
+ throw 210503;
+ menuDestroyer.Attach(popupMenu);
+ commandMapItem.CommandInternalID = kCommandNULL;
+ commandMapItem.Verb = kMainVerb;
+ commandMapItem.HelpString = LangString(IDS_CONTEXT_CAPTION_HELP, 0x02000102);
+ _commandMap.Add(commandMapItem);
+
+ menuItem.wID = currentCommandID++;
+ subIndex = 0;
+ }
+ else
+ {
+ popupMenu.Attach(hMenu);
+ }
+
+ UINT32 contextMenuFlags;
+ if (!ReadContextMenuStatus(contextMenuFlags))
+ contextMenuFlags = NContextMenuFlags::GetDefaultFlags();
+
+ UString mainString;
+ if(_fileNames.Size() == 1 && currentCommandID + 6 <= commandIDLast)
+ {
+ const UString &fileName = _fileNames.Front();
+ UString folderPrefix;
+ NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix);
+
+ NFile::NFind::CFileInfoW fileInfo;
+ if (!NFile::NFind::FindFile(fileName, fileInfo))
+ return E_FAIL;
+ if (!fileInfo.IsDirectory())
+ {
+ // Open
+ if ((contextMenuFlags & NContextMenuFlags::kOpen) != 0)
+ {
+ CCommandMapItem commandMapItem;
+ FillCommand(kOpen, mainString, commandMapItem);
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
+ _commandMap.Add(commandMapItem);
+ }
+ }
+ }
+
+ if(_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast)
+ {
+ bool thereAreFolders = false;
+ for(int i = 0; i < _fileNames.Size(); i++)
+ {
+ NFile::NFind::CFileInfoW fileInfo;
+ if (!NFile::NFind::FindFile(_fileNames[i], fileInfo))
+ return E_FAIL;
+ if (fileInfo.IsDirectory())
+ thereAreFolders = true;
+ }
+ const UString &fileName = _fileNames.Front();
+ if (!thereAreFolders)
+ {
+ UString folderPrefix;
+ NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix);
+ NFile::NFind::CFileInfoW fileInfo;
+ if (!NFile::NFind::FindFile(fileName, fileInfo))
+ return E_FAIL;
+ // Extract
+ if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0)
+ {
+ CCommandMapItem commandMapItem;
+ FillCommand(kExtract, mainString, commandMapItem);
+ if (_dropMode)
+ commandMapItem.Folder = _dropPath;
+ else
+ commandMapItem.Folder = folderPrefix;
+ commandMapItem.Folder += GetSubFolderNameForExtract(fileInfo.Name) + UString(L'\\');
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
+ _commandMap.Add(commandMapItem);
+ }
+
+ // Extract Here
+ if ((contextMenuFlags & NContextMenuFlags::kExtractHere) != 0)
+ {
+ CCommandMapItem commandMapItem;
+ FillCommand(kExtractHere, mainString, commandMapItem);
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
+ if (_dropMode)
+ commandMapItem.Folder = _dropPath;
+ else
+ commandMapItem.Folder = folderPrefix;
+ _commandMap.Add(commandMapItem);
+ }
+
+ // Extract To
+ if ((contextMenuFlags & NContextMenuFlags::kExtractTo) != 0)
+ {
+ CCommandMapItem commandMapItem;
+ UString s;
+ FillCommand(kExtractTo, s, commandMapItem);
+ UString folder;
+ if (_fileNames.Size() == 1)
+ folder = GetSubFolderNameForExtract(fileInfo.Name);
+ else
+ folder = L'*';
+ if (_dropMode)
+ commandMapItem.Folder = _dropPath;
+ else
+ commandMapItem.Folder = folderPrefix;
+ commandMapItem.Folder += folder;
+ s = MyFormatNew(s, GetReducedString(UString(L"\"") + folder + UString(L"\\\"")));
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
+ _commandMap.Add(commandMapItem);
+ }
+ // Test
+ if ((contextMenuFlags & NContextMenuFlags::kTest) != 0)
+ {
+ CCommandMapItem commandMapItem;
+ FillCommand(kTest, mainString, commandMapItem);
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
+ _commandMap.Add(commandMapItem);
+ }
+ }
+ UString archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false);
+ UString archiveName7z = archiveName + L".7z";
+ UString archiveNameZip = archiveName + L".zip";
+ UString archivePathPrefix;
+ NFile::NDirectory::GetOnlyDirPrefix(fileName, archivePathPrefix);
+
+ // Compress
+ if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0)
+ {
+ CCommandMapItem commandMapItem;
+ if (_dropMode)
+ commandMapItem.Folder = _dropPath;
+ else
+ commandMapItem.Folder = archivePathPrefix;
+ commandMapItem.Archive = archiveName;
+ FillCommand(kCompress, mainString, commandMapItem);
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
+ _commandMap.Add(commandMapItem);
+ }
+
+
+ // CompressEmail
+ if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode)
+ {
+ CCommandMapItem commandMapItem;
+ commandMapItem.Archive = archiveName;
+ FillCommand(kCompressEmail, mainString, commandMapItem);
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
+ _commandMap.Add(commandMapItem);
+ }
+
+ // CompressTo7z
+ if (contextMenuFlags & NContextMenuFlags::kCompressTo7z)
+ {
+ CCommandMapItem commandMapItem;
+ UString s;
+ FillCommand(kCompressTo7z, s, commandMapItem);
+ if (_dropMode)
+ commandMapItem.Folder = _dropPath;
+ else
+ commandMapItem.Folder = archivePathPrefix;
+ commandMapItem.Archive = archiveName7z;
+ commandMapItem.ArchiveType = L"7z";
+ UString t = UString(L"\"") + GetReducedString(archiveName7z) + UString(L"\"");
+ s = MyFormatNew(s, t);
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
+ _commandMap.Add(commandMapItem);
+ }
+
+ // CompressTo7zEmail
+ if ((contextMenuFlags & NContextMenuFlags::kCompressTo7zEmail) != 0 && !_dropMode)
+ {
+ CCommandMapItem commandMapItem;
+ UString s;
+ FillCommand(kCompressTo7zEmail, s, commandMapItem);
+ commandMapItem.Archive = archiveName7z;
+ commandMapItem.ArchiveType = L"7z";
+ UString t = UString(L"\"") + GetReducedString(archiveName7z) + UString(L"\"");
+ s = MyFormatNew(s, t);
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
+ _commandMap.Add(commandMapItem);
+ }
+
+ // CompressToZip
+ if (contextMenuFlags & NContextMenuFlags::kCompressToZip)
+ {
+ CCommandMapItem commandMapItem;
+ UString s;
+ FillCommand(kCompressToZip, s, commandMapItem);
+ if (_dropMode)
+ commandMapItem.Folder = _dropPath;
+ else
+ commandMapItem.Folder = archivePathPrefix;
+ commandMapItem.Archive = archiveNameZip;
+ commandMapItem.ArchiveType = L"zip";
+ UString t = UString(L"\"") + GetReducedString(archiveNameZip) + UString(L"\"");
+ s = MyFormatNew(s, t);
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
+ _commandMap.Add(commandMapItem);
+ }
+
+ // CompressToZipEmail
+ if ((contextMenuFlags & NContextMenuFlags::kCompressToZipEmail) != 0 && !_dropMode)
+ {
+ CCommandMapItem commandMapItem;
+ UString s;
+ FillCommand(kCompressToZipEmail, s, commandMapItem);
+ commandMapItem.Archive = archiveNameZip;
+ commandMapItem.ArchiveType = L"zip";
+ UString t = UString(L"\"") + GetReducedString(archiveNameZip) + UString(L"\"");
+ s = MyFormatNew(s, t);
+ MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
+ _commandMap.Add(commandMapItem);
+ }
+ }
+
+
+ // don't use InsertMenu: See MSDN:
+ // PRB: Duplicate Menu Items In the File Menu For a Shell Context Menu Extension
+ // ID: Q214477
+
+ if (cascadedMenu)
+ {
+ CMenuItem menuItem;
+ menuItem.fType = MFT_STRING;
+ menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
+ menuItem.wID = currentCommandID++;
+ menuItem.hSubMenu = popupMenu.Detach();
+ menuDestroyer.Disable();
+ menuItem.StringValue = LangString(IDS_CONTEXT_POPUP_CAPTION, 0x02000101);
+ CMenu menu;
+ menu.Attach(hMenu);
+ menu.InsertItem(indexMenu++, true, menuItem);
+ }
+
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst);
+}
+
+
+int CZipContextMenu::FindVerb(const UString &verb)
+{
+ for(int i = 0; i < _commandMap.Size(); i++)
+ if(_commandMap[i].Verb.Compare(verb) == 0)
+ return i;
+ return -1;
+}
+
+extern const char *kShellFolderClassIDString;
+
+
+static UString GetProgramCommand()
+{
+ UString path = L"\"";
+ UString folder;
+ if (GetProgramFolderPath(folder))
+ path += folder;
+ path += L"7zFM.exe\"";
+ return path;
+}
+
+STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
+{
+ // ::OutputDebugStringA("1");
+ int commandOffset;
+
+ // It's fix for bug: crashing in XP. See example in MSDN: "Creating Context Menu Handlers".
+
+ if (commandInfo->cbSize == sizeof(CMINVOKECOMMANDINFOEX) &&
+ (commandInfo->fMask & CMIC_MASK_UNICODE) != 0)
+ {
+ LPCMINVOKECOMMANDINFOEX commandInfoEx = (LPCMINVOKECOMMANDINFOEX)commandInfo;
+ if(HIWORD(commandInfoEx->lpVerbW) == 0)
+ commandOffset = LOWORD(commandInfo->lpVerb);
+ else
+ commandOffset = FindVerb(commandInfoEx->lpVerbW);
+ }
+ else
+ if(HIWORD(commandInfo->lpVerb) == 0)
+ commandOffset = LOWORD(commandInfo->lpVerb);
+ else
+ commandOffset = FindVerb(GetUnicodeString(commandInfo->lpVerb));
+
+ if(commandOffset < 0 || commandOffset >= _commandMap.Size())
+ return E_FAIL;
+
+ const CCommandMapItem commandMapItem = _commandMap[commandOffset];
+ ECommandInternalID commandInternalID = commandMapItem.CommandInternalID;
+
+ try
+ {
+ switch(commandInternalID)
+ {
+ case kOpen:
+ {
+ UString params;
+ params = GetProgramCommand();
+ params += L" \"";
+ params += _fileNames[0];
+ params += L"\"";
+ MyCreateProcess(params, 0, false, 0);
+ break;
+ }
+ case kExtract:
+ case kExtractHere:
+ case kExtractTo:
+ {
+ ExtractArchives(_fileNames, commandMapItem.Folder,
+ (commandInternalID == kExtract));
+ break;
+ }
+ case kTest:
+ {
+ TestArchives(_fileNames);
+ break;
+ }
+ case kCompress:
+ case kCompressEmail:
+ case kCompressTo7z:
+ case kCompressTo7zEmail:
+ case kCompressToZip:
+ case kCompressToZipEmail:
+ {
+ bool email =
+ (commandInternalID == kCompressEmail) ||
+ (commandInternalID == kCompressTo7zEmail) ||
+ (commandInternalID == kCompressToZipEmail);
+ bool showDialog =
+ (commandInternalID == kCompress) ||
+ (commandInternalID == kCompressEmail);
+ CompressFiles(commandMapItem.Folder,
+ commandMapItem.Archive, commandMapItem.ArchiveType,
+ _fileNames, email, showDialog, false);
+ break;
+ }
+ }
+ }
+ catch(...)
+ {
+ MyMessageBox(IDS_ERROR, 0x02000605);
+ }
+ return S_OK;
+}
+
+static void MyCopyString(void *dest, const wchar_t *src, bool writeInUnicode)
+{
+ if(writeInUnicode)
+ {
+ MyStringCopy((wchar_t *)dest, src);
+ }
+ else
+ lstrcpyA((char *)dest, GetAnsiString(src));
+}
+
+STDMETHODIMP CZipContextMenu::GetCommandString(UINT_PTR commandOffset, UINT uType,
+ UINT * /* pwReserved */ , LPSTR pszName, UINT /* cchMax */)
+{
+ int cmdOffset = (int)commandOffset;
+ switch(uType)
+ {
+ case GCS_VALIDATEA:
+ case GCS_VALIDATEW:
+ if(cmdOffset < 0 || cmdOffset >= _commandMap.Size())
+ return S_FALSE;
+ else
+ return S_OK;
+ }
+ if(cmdOffset < 0 || cmdOffset >= _commandMap.Size())
+ return E_FAIL;
+ if(uType == GCS_HELPTEXTA || uType == GCS_HELPTEXTW)
+ {
+ MyCopyString(pszName, _commandMap[cmdOffset].HelpString, uType == GCS_HELPTEXTW);
+ return NO_ERROR;
+ }
+ if(uType == GCS_VERBA || uType == GCS_VERBW)
+ {
+ MyCopyString(pszName, _commandMap[cmdOffset].Verb, uType == GCS_VERBW);
+ return NO_ERROR;
+ }
+ return E_FAIL;
+}
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h
new file mode 100755
index 00000000..60970a22
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/ContextMenu.h
@@ -0,0 +1,86 @@
+// ContextMenu.h
+
+#ifndef __CONTEXTMENU_H
+#define __CONTEXTMENU_H
+
+// {23170F69-40C1-278A-1000-000100020000}
+DEFINE_GUID(CLSID_CZipContextMenu,
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);
+
+#include "Common/String.h"
+
+#include "../../FileManager/PluginInterface.h"
+#include "../../FileManager/MyCom2.h"
+
+
+class CZipContextMenu:
+ public IContextMenu,
+ public IShellExtInit,
+ public IInitContextMenu,
+ public CMyUnknownImp
+{
+
+public:
+
+ enum ECommandInternalID
+ {
+ kCommandNULL,
+ kOpen,
+ kExtract,
+ kExtractHere,
+ kExtractTo,
+ kTest,
+ kCompress,
+ kCompressEmail,
+ kCompressTo7z,
+ kCompressTo7zEmail,
+ kCompressToZip,
+ kCompressToZipEmail
+ };
+
+ struct CCommandMapItem
+ {
+ ECommandInternalID CommandInternalID;
+ UString Verb;
+ UString HelpString;
+ UString Folder;
+ UString Archive;
+ UString ArchiveType;
+ };
+
+ MY_UNKNOWN_IMP3_MT(IContextMenu, IShellExtInit, IInitContextMenu)
+
+ ///////////////////////////////
+ // IShellExtInit
+
+ STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder,
+ LPDATAOBJECT dataObject, HKEY hkeyProgID);
+
+ /////////////////////////////
+ // IContextMenu
+
+ STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu,
+ UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
+ STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici);
+ STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pwReserved,
+ LPSTR pszName, UINT cchMax);
+
+
+ // IInitContextMenu
+ STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UINT32 numFiles);
+private:
+ UStringVector _fileNames;
+ bool _dropMode;
+ UString _dropPath;
+ CObjectVector<CCommandMapItem> _commandMap;
+ HRESULT GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames);
+ int FindVerb(const UString &verb);
+
+ void FillCommand(ECommandInternalID id, UString &mainString,
+ CCommandMapItem &commandMapItem);
+public:
+ CZipContextMenu();
+ ~CZipContextMenu();
+};
+
+#endif
diff --git a/CPP/7zip/UI/Explorer/ContextMenuFlags.h b/CPP/7zip/UI/Explorer/ContextMenuFlags.h
new file mode 100755
index 00000000..d138baf9
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/ContextMenuFlags.h
@@ -0,0 +1,34 @@
+// ContextMenuFlags.h
+
+#ifndef __SEVENZIP_CONTEXTMENUFLAGS_H
+#define __SEVENZIP_CONTEXTMENUFLAGS_H
+
+namespace NContextMenuFlags
+{
+ const UINT32 kExtract = 1 << 0;
+ const UINT32 kExtractHere = 1 << 1;
+ const UINT32 kExtractTo = 1 << 2;
+ // const UINT32 kExtractEach = 1 << 3;
+
+ const UINT32 kTest = 1 << 4;
+
+ const UINT32 kOpen = 1 << 5;
+
+ const UINT32 kCompress = 1 << 8;
+ const UINT32 kCompressTo7z = 1 << 9;
+ const UINT32 kCompressEmail = 1 << 10;
+ const UINT32 kCompressTo7zEmail = 1 << 11;
+
+ const UINT32 kCompressToZip = 1 << 12;
+ const UINT32 kCompressToZipEmail = 1 << 13;
+
+ inline UINT32 GetDefaultFlags() {
+ return
+ kOpen | kTest |
+ kExtract | kExtractHere | kExtractTo |
+ kCompress | kCompressEmail |
+ kCompressTo7z | kCompressTo7zEmail |
+ kCompressToZip | kCompressToZipEmail; }
+}
+
+#endif
diff --git a/CPP/7zip/UI/Explorer/DllExports.cpp b/CPP/7zip/UI/Explorer/DllExports.cpp
new file mode 100755
index 00000000..fb7daf04
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/DllExports.cpp
@@ -0,0 +1,315 @@
+// DLLExports.cpp
+//
+// Notes:
+// Win2000:
+// If I register at HKCR\Folder\ShellEx then DLL is locked.
+// otherwise it unloads after explorer closing.
+// but if I call menu for desktop items it's locked all the time
+
+#include "StdAfx.h"
+
+// #include <locale.h>
+
+#include <initguid.h>
+#include <windows.h>
+#include <ShlGuid.h>
+#include <OleCtl.h>
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+#include "Windows/DLL.h"
+#include "Windows/Registry.h"
+
+#include "../../IPassword.h"
+#include "../../FileManager/LangUtils.h"
+#include "../Agent/Agent.h"
+
+#include "ContextMenu.h"
+#include "OptionsDialog.h"
+
+using namespace NWindows;
+
+HINSTANCE g_hInstance;
+#ifndef _UNICODE
+bool g_IsNT = false;
+#endif
+
+LONG g_DllRefCount = 0; // Reference count of this DLL.
+
+static LPCWSTR kShellExtName = L"7-Zip Shell Extension";
+static LPCTSTR kClsidMask = TEXT("CLSID\\%s");
+static LPCTSTR kClsidInprocMask = TEXT("CLSID\\%s\\InprocServer32");
+static LPCTSTR kApprovedKeyPath = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved");
+
+// #define ODS(sz) OutputDebugString(L#sz)
+
+class CShellExtClassFactory:
+ public IClassFactory,
+ public CMyUnknownImp
+{
+public:
+ CShellExtClassFactory() { InterlockedIncrement(&g_DllRefCount); }
+ ~CShellExtClassFactory() { InterlockedDecrement(&g_DllRefCount); }
+
+
+ MY_UNKNOWN_IMP1_MT(IClassFactory)
+
+ STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, void**);
+ STDMETHODIMP LockServer(BOOL);
+};
+
+STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
+ REFIID riid, void **ppvObj)
+{
+ // ODS("CShellExtClassFactory::CreateInstance()\r\n");
+ *ppvObj = NULL;
+ if (pUnkOuter)
+ return CLASS_E_NOAGGREGATION;
+
+ CZipContextMenu *shellExt;
+ try
+ {
+ shellExt = new CZipContextMenu();
+ }
+ catch(...) { return E_OUTOFMEMORY; }
+ if (shellExt == NULL)
+ return E_OUTOFMEMORY;
+
+ HRESULT res = shellExt->QueryInterface(riid, ppvObj);
+ if (res != S_OK)
+ delete shellExt;
+ return res;
+}
+
+
+STDMETHODIMP CShellExtClassFactory::LockServer(BOOL /* fLock */)
+{
+ return S_OK; // Check it
+}
+
+static bool IsItWindowsNT()
+{
+ OSVERSIONINFO versionInfo;
+ versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+ if (!::GetVersionEx(&versionInfo))
+ return false;
+ return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
+{
+ // setlocale(LC_COLLATE, ".ACP");
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ g_hInstance = hInstance;
+ // ODS("In DLLMain, DLL_PROCESS_ATTACH\r\n");
+ #ifdef _UNICODE
+ if (!IsItWindowsNT())
+ return FALSE;
+ #else
+ g_IsNT = IsItWindowsNT();
+ #endif
+ }
+ else if (dwReason == DLL_PROCESS_DETACH)
+ {
+ // ODS("In DLLMain, DLL_PROCESS_DETACH\r\n");
+ }
+ return TRUE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Used to determine whether the DLL can be unloaded by OLE
+
+STDAPI DllCanUnloadNow(void)
+{
+ // ODS("In DLLCanUnloadNow\r\n");
+ return (g_DllRefCount == 0 ? S_OK : S_FALSE);
+}
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+ // ODS("In DllGetClassObject\r\n");
+ *ppv = NULL;
+ if (IsEqualIID(rclsid, CLSID_CZipContextMenu))
+ {
+ CShellExtClassFactory *cf;
+ try
+ {
+ cf = new CShellExtClassFactory;
+ }
+ catch(...) { return E_OUTOFMEMORY; }
+ if (cf == 0)
+ return E_OUTOFMEMORY;
+ HRESULT res = cf->QueryInterface(riid, ppv);
+ if (res != S_OK)
+ delete cf;
+ return res;
+ }
+ return CLASS_E_CLASSNOTAVAILABLE;
+ // return _Module.GetClassObject(rclsid, riid, ppv);
+}
+
+static BOOL GetStringFromIID(CLSID clsid, LPTSTR s, int size)
+{
+ LPWSTR pwsz;
+ if (StringFromIID(clsid, &pwsz) != S_OK)
+ return FALSE;
+ if(!pwsz)
+ return FALSE;
+ #ifdef UNICODE
+ lstrcpyn(s, pwsz, size);
+ #else
+ WideCharToMultiByte(CP_ACP, 0, pwsz, -1, s, size, NULL, NULL);
+ #endif
+ CoTaskMemFree(pwsz);
+ s[size - 1] = 0;
+ return TRUE;
+}
+
+typedef struct
+{
+ HKEY hRootKey;
+ LPCTSTR SubKey;
+ LPCWSTR ValueName;
+ LPCWSTR Data;
+} CRegItem;
+
+static BOOL RegisterServer(CLSID clsid, LPCWSTR title)
+{
+ TCHAR clsidString[MAX_PATH];
+ if (!GetStringFromIID(clsid, clsidString, MAX_PATH))
+ return FALSE;
+
+ UString modulePath;
+ if (!NDLL::MyGetModuleFileName(g_hInstance, modulePath))
+ return FALSE;
+
+ CRegItem clsidEntries[] =
+ {
+ HKEY_CLASSES_ROOT, kClsidMask, NULL, title,
+ HKEY_CLASSES_ROOT, kClsidInprocMask, NULL, modulePath,
+ HKEY_CLASSES_ROOT, kClsidInprocMask, L"ThreadingModel", L"Apartment",
+ NULL, NULL, NULL, NULL
+ };
+
+ //register the CLSID entries
+ for(int i = 0; clsidEntries[i].hRootKey; i++)
+ {
+ TCHAR subKey[MAX_PATH];
+ wsprintf(subKey, clsidEntries[i].SubKey, clsidString);
+ NRegistry::CKey key;
+ if (key.Create(clsidEntries[i].hRootKey, subKey, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_WRITE) != NOERROR)
+ return FALSE;
+ key.SetValue(clsidEntries[i].ValueName, clsidEntries[i].Data);
+ }
+
+ if(IsItWindowsNT())
+ {
+ NRegistry::CKey key;
+ if (key.Create(HKEY_LOCAL_MACHINE, kApprovedKeyPath, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_WRITE) == NOERROR)
+ key.SetValue(GetUnicodeString(clsidString), title);
+ }
+ return TRUE;
+}
+
+STDAPI DllRegisterServer(void)
+{
+ return RegisterServer(CLSID_CZipContextMenu, kShellExtName) ? S_OK: SELFREG_E_CLASS;
+}
+
+static BOOL UnregisterServer(CLSID clsid)
+{
+ TCHAR clsidString[MAX_PATH];
+ if (!GetStringFromIID(clsid, clsidString, MAX_PATH))
+ return FALSE;
+
+ TCHAR subKey[MAX_PATH];
+ wsprintf(subKey, kClsidInprocMask, clsidString);
+ RegDeleteKey(HKEY_CLASSES_ROOT, subKey);
+
+ wsprintf (subKey, kClsidMask, clsidString);
+ RegDeleteKey(HKEY_CLASSES_ROOT, subKey);
+
+ if(IsItWindowsNT())
+ {
+ HKEY hKey;
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, kApprovedKeyPath, 0, KEY_SET_VALUE, &hKey) == NOERROR)
+ {
+ RegDeleteValue(hKey, clsidString);
+ RegCloseKey(hKey);
+ }
+ }
+ return TRUE;
+}
+
+STDAPI DllUnregisterServer(void)
+{
+ return UnregisterServer(CLSID_CZipContextMenu) ? S_OK: SELFREG_E_CLASS;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ LoadLangOneTime();
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID == CLSID_CAgentArchiveHandler)
+ {
+ if (*interfaceID == IID_IFolderManager)
+ {
+ CMyComPtr<IFolderManager> manager = new CArchiveFolderManager;
+ *outObject = manager.Detach();
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+ }
+ if (*classID == CLSID_CSevenZipOptions)
+ {
+ if (*interfaceID == IID_IPluginOptions)
+ {
+ CMyComPtr<IPluginOptions> options = new CSevenZipOptions;
+ *outObject = options.Detach();
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+ }
+ return CLASS_E_CLASSNOTAVAILABLE;
+ COM_TRY_END
+}
+
+STDAPI GetPluginProperty(PROPID propID, PROPVARIANT *value)
+{
+ ::VariantClear((tagVARIANT *)value);
+ switch(propID)
+ {
+ case NPlugin::kName:
+ if ((value->bstrVal = ::SysAllocString(L"7-Zip")) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ case NPlugin::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CAgentArchiveHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NPlugin::kOptionsClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CSevenZipOptions, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ /*
+ case NArchive::kType:
+ propVariant = UINT32(0);
+ break;
+ */
+ }
+ return S_OK;
+}
diff --git a/CPP/7zip/UI/Explorer/Explorer.def b/CPP/7zip/UI/Explorer/Explorer.def
new file mode 100755
index 00000000..752fbb7a
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/Explorer.def
@@ -0,0 +1,12 @@
+; 7-zip.def
+
+LIBRARY "7-zip"
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
+
+ CreateObject PRIVATE
+ GetPluginProperty PRIVATE
diff --git a/CPP/7zip/UI/Explorer/Explorer.dsp b/CPP/7zip/UI/Explorer/Explorer.dsp
new file mode 100755
index 00000000..c395c6d2
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/Explorer.dsp
@@ -0,0 +1,818 @@
+# Microsoft Developer Studio Project File - Name="Explorer" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Explorer - Win32 DebugU
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Explorer.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Explorer.mak" CFG="Explorer - Win32 DebugU"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Explorer - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Explorer - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Explorer - Win32 ReleaseU" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Explorer - Win32 DebugU" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Explorer - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /D "NEW_FOLDER_INTERFACE" /Yu"StdAfx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Explorer - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /D "NEW_FOLDER_INTERFACE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "Explorer - Win32 ReleaseU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseU"
+# PROP BASE Intermediate_Dir "ReleaseU"
+# PROP BASE Ignore_Export_Lib 1
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseU"
+# PROP Intermediate_Dir "ReleaseU"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /D "_MBCS" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /D "NEW_FOLDER_INTERFACE" /Yu"StdAfx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /opt:NOWIN98
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zipn.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Explorer - Win32 DebugU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DebugU"
+# PROP BASE Intermediate_Dir "DebugU"
+# PROP BASE Ignore_Export_Lib 1
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugU"
+# PROP Intermediate_Dir "DebugU"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "EXPLORER_EXPORTS" /D "LANG" /D "NEW_FOLDER_INTERFACE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Explorer - Win32 Release"
+# Name "Explorer - Win32 Debug"
+# Name "Explorer - Win32 ReleaseU"
+# Name "Explorer - Win32 DebugU"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\DllExports.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Explorer.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "UI Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\ArchiveExtractCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveOpenCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveOpenCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiverInfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiverInfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\CompressCall.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\CompressCall.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DefaultName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DefaultName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\EnumDirItems.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\EnumDirItems.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExtractingFilePath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExtractingFilePath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\HandlerLoader.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\OpenArchive.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\OpenArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\PropIDUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\PropIDUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SortUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SortUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateAction.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateAction.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdatePair.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdatePair.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateProduce.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateProduce.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\WorkDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\WorkDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ZipRegistry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ZipRegistry.h
+# End Source File
+# End Group
+# Begin Group "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ContextMenu.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ContextMenu.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyMessages.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyMessages.h
+# End Source File
+# End Group
+# Begin Group "Dialogs"
+
+# PROP Default_Filter ""
+# Begin Group "Options"
+
+# PROP Default_Filter ""
+# Begin Group "SystemPage"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\SystemPage\SystemPage.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SystemPage\SystemPage.h
+# End Source File
+# End Group
+# Begin Group "FoldersPage"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\FoldersPage\FoldersPage.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\FoldersPage\FoldersPage.h
+# End Source File
+# End Group
+# End Group
+# End Group
+# Begin Group "Agent"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Agent\Agent.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\Agent.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\AgentOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\AgentProxy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\AgentProxy.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\ArchiveFolder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\ArchiveFolderOpen.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\ArchiveFolderOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\IFileExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\IFolderArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\UpdateCallbackAgent.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\UpdateCallbackAgent.h
+# End Source File
+# End Group
+# Begin Group "FileManager"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\FileManager\FormatUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\FormatUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\HelpUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\HelpUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\IFolder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\LangUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\LangUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\ProgramLocation.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\ProgramLocation.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\RegistryUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\RegistryUtils.h
+# End Source File
+# End Group
+# Begin Group "SDK"
+
+# PROP Default_Filter ""
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\Alloc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Alloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Lang.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Lang.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyCom.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Random.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Random.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\TextConfig.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\TextConfig.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Group "Control"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\Dialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\Dialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\PropertyPage.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\PropertyPage.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Error.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileMapping.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Memory.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Memory.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Menu.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Menu.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Registry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Registry.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ResourceString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ResourceString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Shell.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Shell.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Window.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Window.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "7-zip common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\FilePathAutoRename.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FilePathAutoRename.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.h
+# End Source File
+# End Group
+# Begin Group "C"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sort.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sort.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=".\7-zip.dll.manifest"
+# End Source File
+# Begin Source File
+
+SOURCE=.\ContextMenuFlags.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RegistryContextMenu.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RegistryContextMenu.h
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/UI/Explorer/Explorer.dsw b/CPP/7zip/UI/Explorer/Explorer.dsw
new file mode 100755
index 00000000..beb8df7b
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/Explorer.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Explorer"=".\Explorer.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/UI/Explorer/FoldersPage/FoldersPage.cpp b/CPP/7zip/UI/Explorer/FoldersPage/FoldersPage.cpp
new file mode 100755
index 00000000..776813d8
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/FoldersPage/FoldersPage.cpp
@@ -0,0 +1,157 @@
+// FoldersPage.cpp
+
+#include "StdAfx.h"
+
+#include "resource.h"
+#include "FoldersPage.h"
+
+#include "Common/StringConvert.h"
+#include "Windows/Defs.h"
+#include "Windows/Shell.h"
+#include "Windows/ResourceString.h"
+
+#include "../../../FileManager/HelpUtils.h"
+#include "../../Common/ZipRegistry.h"
+
+#include "../../../FileManager/LangUtils.h"
+
+using namespace NWindows;
+
+static CIDLangPair kIDLangPairs[] =
+{
+ { IDC_FOLDERS_STATIC_WORKING_FOLDER, 0x01000210 },
+ { IDC_FOLDERS_WORK_RADIO_SYSTEM, 0x01000211 },
+ { IDC_FOLDERS_WORK_RADIO_CURRENT, 0x01000212 },
+ { IDC_FOLDERS_WORK_RADIO_SPECIFIED, 0x01000213 },
+ { IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE, 0x01000214 }
+};
+
+static const int kWorkModeButtons[] =
+{
+ IDC_FOLDERS_WORK_RADIO_SYSTEM,
+ IDC_FOLDERS_WORK_RADIO_CURRENT,
+ IDC_FOLDERS_WORK_RADIO_SPECIFIED
+};
+
+static const int kNumWorkModeButtons = sizeof(kWorkModeButtons) / sizeof(kWorkModeButtons[0]);
+
+bool CFoldersPage::OnInit()
+{
+ LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));
+ ReadWorkDirInfo(m_WorkDirInfo);
+
+ CheckButton(IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE, m_WorkDirInfo.ForRemovableOnly);
+
+ CheckRadioButton(kWorkModeButtons[0], kWorkModeButtons[kNumWorkModeButtons - 1],
+ kWorkModeButtons[m_WorkDirInfo.Mode]);
+
+ m_WorkPath.Init(*this, IDC_FOLDERS_WORK_EDIT_PATH);
+ m_ButtonSetWorkPath.Init(*this, IDC_FOLDERS_WORK_BUTTON_PATH);
+
+ m_WorkPath.SetText(m_WorkDirInfo.Path);
+
+ MyEnableControls();
+
+ return CPropertyPage::OnInit();
+}
+
+int CFoldersPage::GetWorkMode() const
+{
+ for (int i = 0; i < kNumWorkModeButtons; i++)
+ if(IsButtonCheckedBool(kWorkModeButtons[i]))
+ return i;
+ throw 0;
+}
+
+void CFoldersPage::MyEnableControls()
+{
+ bool enablePath = (GetWorkMode() == NWorkDir::NMode::kSpecified);
+ m_WorkPath.Enable(enablePath);
+ m_ButtonSetWorkPath.Enable(enablePath);
+}
+
+void CFoldersPage::GetWorkDir(NWorkDir::CInfo &workDirInfo)
+{
+ m_WorkPath.GetText(workDirInfo.Path);
+ workDirInfo.ForRemovableOnly = IsButtonCheckedBool(IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE);
+ workDirInfo.Mode = NWorkDir::NMode::EEnum(GetWorkMode());
+}
+
+/*
+bool CFoldersPage::WasChanged()
+{
+ NWorkDir::CInfo workDirInfo;
+ GetWorkDir(workDirInfo);
+ return (workDirInfo.Mode != m_WorkDirInfo.Mode ||
+ workDirInfo.ForRemovableOnly != m_WorkDirInfo.ForRemovableOnly ||
+ workDirInfo.Path.Compare(m_WorkDirInfo.Path) != 0);
+}
+*/
+
+void CFoldersPage::ModifiedEvent()
+{
+ Changed();
+ /*
+ if (WasChanged())
+ Changed();
+ else
+ UnChanged();
+ */
+}
+
+bool CFoldersPage::OnButtonClicked(int buttonID, HWND buttonHWND)
+{
+ for (int i = 0; i < kNumWorkModeButtons; i++)
+ if (buttonID == kWorkModeButtons[i])
+ {
+ MyEnableControls();
+ ModifiedEvent();
+ return true;
+ }
+ switch(buttonID)
+ {
+ case IDC_FOLDERS_WORK_BUTTON_PATH:
+ OnFoldersWorkButtonPath();
+ break;
+ case IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE:
+ break;
+ default:
+ return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
+ }
+ ModifiedEvent();
+ return true;
+}
+
+bool CFoldersPage::OnCommand(int code, int itemID, LPARAM lParam)
+{
+ if (code == EN_CHANGE && itemID == IDC_FOLDERS_WORK_EDIT_PATH)
+ {
+ ModifiedEvent();
+ return true;
+ }
+ return CPropertyPage::OnCommand(code, itemID, lParam);
+}
+
+void CFoldersPage::OnFoldersWorkButtonPath()
+{
+ UString currentPath;
+ m_WorkPath.GetText(currentPath);
+ UString title = LangString(IDS_FOLDERS_SET_WORK_PATH_TITLE, 0x01000281);
+ UString resultPath;
+ if (NShell::BrowseForFolder(HWND(*this), title, currentPath, resultPath))
+ m_WorkPath.SetText(resultPath);
+}
+
+LONG CFoldersPage::OnApply()
+{
+ GetWorkDir(m_WorkDirInfo);
+ SaveWorkDirInfo(m_WorkDirInfo);
+ return PSNRET_NOERROR;
+}
+
+static LPCWSTR kFoldersTopic = L"fm/plugins/7-zip/options.htm#folders";
+
+void CFoldersPage::OnNotifyHelp()
+{
+ ShowHelpWindow(NULL, kFoldersTopic);
+}
diff --git a/CPP/7zip/UI/Explorer/FoldersPage/FoldersPage.h b/CPP/7zip/UI/Explorer/FoldersPage/FoldersPage.h
new file mode 100755
index 00000000..97950fc6
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/FoldersPage/FoldersPage.h
@@ -0,0 +1,30 @@
+// FoldersPage.h
+
+#ifndef __FOLDERSPAGE_H
+#define __FOLDERSPAGE_H
+
+#include "Windows/Control/PropertyPage.h"
+
+#include "../../Common/ZipRegistry.h"
+
+class CFoldersPage : public NWindows::NControl::CPropertyPage
+{
+ NWorkDir::CInfo m_WorkDirInfo;
+
+ void MyEnableControls();
+ void ModifiedEvent();
+ NWindows::NControl::CDialogChildControl m_WorkPath;
+ NWindows::NControl::CDialogChildControl m_ButtonSetWorkPath;
+ void OnFoldersWorkButtonPath();
+ int GetWorkMode() const;
+ void GetWorkDir(NWorkDir::CInfo &workDirInfo);
+ // bool WasChanged();
+public:
+ virtual bool OnInit();
+ virtual bool OnCommand(int code, int itemID, LPARAM lParam);
+ virtual void OnNotifyHelp();
+ virtual LONG OnApply();
+ virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
+};
+
+#endif
diff --git a/CPP/7zip/UI/Explorer/FoldersPage/resource.h b/CPP/7zip/UI/Explorer/FoldersPage/resource.h
new file mode 100755
index 00000000..3052409b
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/FoldersPage/resource.h
@@ -0,0 +1,12 @@
+#define IDD_FOLDERS 900
+
+#define IDS_FOLDERS_SET_WORK_PATH_TITLE 103
+
+#define IDC_FOLDERS_STATIC_WORKING_FOLDER 1001
+
+#define IDC_FOLDERS_WORK_RADIO_SYSTEM 1011
+#define IDC_FOLDERS_WORK_RADIO_CURRENT 1012
+#define IDC_FOLDERS_WORK_RADIO_SPECIFIED 1013
+#define IDC_FOLDERS_WORK_EDIT_PATH 1014
+#define IDC_FOLDERS_WORK_BUTTON_PATH 1015
+#define IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE 1017
diff --git a/CPP/7zip/UI/Explorer/FoldersPage/resource.rc b/CPP/7zip/UI/Explorer/FoldersPage/resource.rc
new file mode 100755
index 00000000..96b2c9d3
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/FoldersPage/resource.rc
@@ -0,0 +1,36 @@
+#include "resource.h"
+#include "../../../GuiCommon.rc"
+
+#define xSize2 196
+#define ySize2 140
+#define xSize (xSize2 + marg + marg)
+#define ySize (ySize2 + marg + marg)
+
+#define marg2 marg
+#define marg3 10
+#define gPos (marg + marg2)
+#define gSize (xSize2 - marg2 - marg2)
+#define gPos2 (gPos + marg3)
+
+
+IDD_FOLDERS DIALOG 0, 0, xSize, ySize MY_PAGE_STYLE
+CAPTION "Folders"
+MY_FONT
+BEGIN
+ GROUPBOX "&Working folder", IDC_FOLDERS_STATIC_WORKING_FOLDER, marg, marg, xSize2, 98
+ CONTROL "&System temp folder", IDC_FOLDERS_WORK_RADIO_SYSTEM, "Button", BS_AUTORADIOBUTTON | WS_GROUP,
+ gPos, 20, gSize, 10
+ CONTROL "&Current", IDC_FOLDERS_WORK_RADIO_CURRENT, "Button", BS_AUTORADIOBUTTON,
+ gPos, 34, gSize, 10
+ CONTROL "Specified:", IDC_FOLDERS_WORK_RADIO_SPECIFIED, "Button", BS_AUTORADIOBUTTON,
+ gPos, 48, gSize, 10
+ EDITTEXT IDC_FOLDERS_WORK_EDIT_PATH, gPos2, 63, gSize - marg3 - bDotsSize - 10, 14, ES_AUTOHSCROLL
+ PUSHBUTTON "...", IDC_FOLDERS_WORK_BUTTON_PATH, xSize - marg - marg2 - bDotsSize, 63, bDotsSize, bYSize
+ CONTROL "Use for removable drives only", IDC_FOLDERS_WORK_CHECK_FOR_REMOVABLE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
+ gPos, 87, gSize, 10
+END
+
+STRINGTABLE
+BEGIN
+ IDS_FOLDERS_SET_WORK_PATH_TITLE "Specify a location for temporary archive files."
+END
diff --git a/CPP/7zip/UI/Explorer/MyMessages.cpp b/CPP/7zip/UI/Explorer/MyMessages.cpp
new file mode 100755
index 00000000..61d2429d
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/MyMessages.cpp
@@ -0,0 +1,58 @@
+// MyMessages.cpp
+
+#include "StdAfx.h"
+
+#include "MyMessages.h"
+#include "Common/String.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/Error.h"
+#include "Windows/ResourceString.h"
+
+#ifdef LANG
+#include "../../FileManager/LangUtils.h"
+#endif
+
+using namespace NWindows;
+
+void MyMessageBox(HWND window, LPCWSTR message)
+{
+ ::MessageBoxW(window, message, L"7-Zip", 0);
+}
+
+void MyMessageBoxResource(HWND window, UINT32 id
+ #ifdef LANG
+ ,UINT32 langID
+ #endif
+ )
+{
+ #ifdef LANG
+ MyMessageBox(window, LangString(id, langID));
+ #else
+ MyMessageBox(window, MyLoadStringW(id));
+ #endif
+}
+
+void MyMessageBox(UINT32 id
+ #ifdef LANG
+ ,UINT32 langID
+ #endif
+ )
+{
+ MyMessageBoxResource(0, id
+ #ifdef LANG
+ , langID
+ #endif
+ );
+}
+
+void ShowErrorMessage(HWND window, DWORD message)
+{
+ MyMessageBox(window, NError::MyFormatMessageW(message));
+}
+
+void ShowLastErrorMessage(HWND window)
+{
+ ShowErrorMessage(window, ::GetLastError());
+}
+
diff --git a/CPP/7zip/UI/Explorer/MyMessages.h b/CPP/7zip/UI/Explorer/MyMessages.h
new file mode 100755
index 00000000..1a96f569
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/MyMessages.h
@@ -0,0 +1,30 @@
+// MyMessages.h
+
+#ifndef __MYMESSAGES_H
+#define __MYMESSAGES_H
+
+#include "Common/String.h"
+
+void MyMessageBox(HWND window, LPCWSTR message);
+
+inline void MyMessageBox(LPCWSTR message)
+ { MyMessageBox(0, message); }
+
+void MyMessageBoxResource(HWND window, UINT32 id
+ #ifdef LANG
+ ,UINT32 langID
+ #endif
+ );
+
+void MyMessageBox(UINT32 id
+ #ifdef LANG
+ ,UINT32 langID
+ #endif
+ );
+
+void ShowErrorMessage(HWND window, DWORD errorMessage);
+inline void ShowErrorMessage(DWORD errorMessage)
+ { ShowErrorMessage(0, errorMessage); }
+void ShowLastErrorMessage(HWND window = 0);
+
+#endif
diff --git a/CPP/7zip/UI/Explorer/OptionsDialog.cpp b/CPP/7zip/UI/Explorer/OptionsDialog.cpp
new file mode 100755
index 00000000..b7831afd
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/OptionsDialog.cpp
@@ -0,0 +1,71 @@
+// OptionsDialog.cpp
+
+#include "StdAfx.h"
+
+#include "resource.h"
+
+#include "OptionsDialog.h"
+
+#include "Common/StringConvert.h"
+#include "Windows/Control/PropertyPage.h"
+
+#include "../../FileManager/LangUtils.h"
+#include "FoldersPage/FoldersPage.h"
+#include "FoldersPage/resource.h"
+#include "SystemPage/SystemPage.h"
+#include "SystemPage/resource.h"
+
+using namespace NWindows;
+
+static INT_PTR OptionsDialog(HWND hwndOwner)
+{
+ CSystemPage systemPage;
+ CFoldersPage foldersPage;
+ UINT32 langIDs[] = { 0x01000300, 0x01000200};
+ UINT pageIDs[] = { IDD_SYSTEM, IDD_FOLDERS};
+ NControl::CPropertyPage *pagePinters[] = { &systemPage, &foldersPage };
+ CObjectVector<NControl::CPageInfo> pages;
+ const int kNumPages = sizeof(langIDs) / sizeof(langIDs[0]);
+ for (int i = 0; i < kNumPages; i++)
+ {
+ NControl::CPageInfo page;
+ page.Title = LangString(langIDs[i]);
+ page.ID = pageIDs[i];
+ page.Page = pagePinters[i];
+ pages.Add(page);
+ }
+ return NControl::MyPropertySheet(pages, hwndOwner,
+ LangString(IDS_CONFIG_DIALOG_CAPTION, 0x01000000));
+}
+
+STDMETHODIMP CSevenZipOptions::PluginOptions(HWND hWnd,
+ IPluginOptionsCallback * /* callback */)
+{
+ /*
+ CComBSTR programPath;
+ RETUEN_IF_NOT_S_OK(callback->GetProgramPath(programName)));
+ */
+ OptionsDialog(hWnd);
+ return S_OK;
+}
+
+STDMETHODIMP CSevenZipOptions::GetFileExtensions(BSTR * /* extensions */)
+{
+ /*
+ UString extStrings;
+ CObjectVector<NZipRootRegistry::CArchiverInfo> formats;
+ NZipRootRegistry::ReadArchiverInfoList(formats);
+ for(int i = 0; i < formats.Size(); i++)
+ {
+ if (i != 0)
+ extStrings += L' ';
+ extStrings += formats[i].Extension;
+ }
+ CComBSTR valueTemp = extStrings;
+ *extensions = valueTemp.Detach();
+ return S_OK;
+ */
+ return E_NOTIMPL;
+}
+
+
diff --git a/CPP/7zip/UI/Explorer/OptionsDialog.h b/CPP/7zip/UI/Explorer/OptionsDialog.h
new file mode 100755
index 00000000..7e85d357
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/OptionsDialog.h
@@ -0,0 +1,23 @@
+// OptionsDialog.h
+
+#ifndef __SEVENZIP_OPTIONSDIALOG_H
+#define __SEVENZIP_OPTIONSDIALOG_H
+
+#include "../../FileManager/PluginInterface.h"
+#include "Common/MyCom.h"
+
+// {23170F69-40C1-278D-1000-000100020000}
+DEFINE_GUID(CLSID_CSevenZipOptions,
+ 0x23170F69, 0x40C1, 0x278D, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);
+
+class CSevenZipOptions:
+ public IPluginOptions,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+ STDMETHOD(PluginOptions)(HWND hWnd, IPluginOptionsCallback *callback);
+ STDMETHOD(GetFileExtensions)(BSTR *extensions);
+};
+
+#endif
diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp
new file mode 100755
index 00000000..73a8420e
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp
@@ -0,0 +1,128 @@
+// RegistryContextMenu.cpp
+
+#include "StdAfx.h"
+
+#include "RegistryContextMenu.h"
+#include "Windows/COM.h"
+#include "Windows/Synchronization.h"
+#include "Windows/Registry.h"
+#include "Windows/FileName.h"
+
+using namespace NWindows;
+using namespace NCOM;
+using namespace NRegistry;
+
+namespace NZipRootRegistry {
+
+static NSynchronization::CCriticalSection g_RegistryOperationsCriticalSection;
+
+///////////////////////////
+// ContextMenu
+
+static const TCHAR *kContextMenuKeyName = TEXT("\\shellex\\ContextMenuHandlers\\7-ZIP");
+static const TCHAR *kDragDropMenuKeyName = TEXT("\\shellex\\DragDropHandlers\\7-ZIP");
+
+static const TCHAR *kExtensionCLSID = TEXT("{23170F69-40C1-278A-1000-000100020000}");
+
+static const TCHAR *kRootKeyNameForFile = TEXT("*");
+static const TCHAR *kRootKeyNameForFolder = TEXT("Folder");
+static const TCHAR *kRootKeyNameForDirectory = TEXT("Directory");
+static const TCHAR *kRootKeyNameForDrive = TEXT("Drive");
+
+static CSysString GetFullContextMenuKeyName(const CSysString &keyName)
+ { return (keyName + kContextMenuKeyName); }
+
+static CSysString GetFullDragDropMenuKeyName(const CSysString &keyName)
+ { return (keyName + kDragDropMenuKeyName); }
+
+static bool CheckContextMenuHandlerCommon(const CSysString &keyName)
+{
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey key;
+ if (key.Open(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(keyName), KEY_READ)
+ != ERROR_SUCCESS)
+ return false;
+ CSysString value;
+ if (key.QueryValue(NULL, value) != ERROR_SUCCESS)
+ return false;
+ return (value.CompareNoCase(kExtensionCLSID) == 0);
+}
+
+static bool CheckDragDropMenuHandlerCommon(const CSysString &keyName)
+{
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey key;
+ if (key.Open(HKEY_CLASSES_ROOT, GetFullDragDropMenuKeyName(keyName), KEY_READ) != ERROR_SUCCESS)
+ return false;
+ CSysString value;
+ if (key.QueryValue(NULL, value) != ERROR_SUCCESS)
+ return false;
+ return (value.CompareNoCase(kExtensionCLSID) == 0);
+}
+
+bool CheckContextMenuHandler()
+{
+ return CheckContextMenuHandlerCommon(kRootKeyNameForFile) &&
+ // CheckContextMenuHandlerCommon(kRootKeyNameForFolder) &&
+ CheckContextMenuHandlerCommon(kRootKeyNameForDirectory) &&
+ CheckDragDropMenuHandlerCommon(kRootKeyNameForDirectory) &&
+ CheckDragDropMenuHandlerCommon(kRootKeyNameForDrive);
+}
+
+static void DeleteContextMenuHandlerCommon(const CSysString &keyName)
+{
+ CKey rootKey;
+ rootKey.Attach(HKEY_CLASSES_ROOT);
+ rootKey.RecurseDeleteKey(GetFullContextMenuKeyName(keyName));
+ rootKey.Detach();
+}
+
+static void DeleteDragDropMenuHandlerCommon(const CSysString &keyName)
+{
+ CKey rootKey;
+ rootKey.Attach(HKEY_CLASSES_ROOT);
+ rootKey.RecurseDeleteKey(GetFullDragDropMenuKeyName(keyName));
+ rootKey.Detach();
+}
+
+void DeleteContextMenuHandler()
+{
+ DeleteContextMenuHandlerCommon(kRootKeyNameForFile);
+ DeleteContextMenuHandlerCommon(kRootKeyNameForFolder);
+ DeleteContextMenuHandlerCommon(kRootKeyNameForDirectory);
+ DeleteContextMenuHandlerCommon(kRootKeyNameForDrive);
+ DeleteDragDropMenuHandlerCommon(kRootKeyNameForFile);
+ DeleteDragDropMenuHandlerCommon(kRootKeyNameForFolder);
+ DeleteDragDropMenuHandlerCommon(kRootKeyNameForDirectory);
+ DeleteDragDropMenuHandlerCommon(kRootKeyNameForDrive);
+}
+
+static void AddContextMenuHandlerCommon(const CSysString &keyName)
+{
+ DeleteContextMenuHandlerCommon(keyName);
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey key;
+ key.Create(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(keyName));
+ key.SetValue(NULL, kExtensionCLSID);
+}
+
+static void AddDragDropMenuHandlerCommon(const CSysString &keyName)
+{
+ DeleteDragDropMenuHandlerCommon(keyName);
+ NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
+ CKey key;
+ key.Create(HKEY_CLASSES_ROOT, GetFullDragDropMenuKeyName(keyName));
+ key.SetValue(NULL, kExtensionCLSID);
+}
+
+void AddContextMenuHandler()
+{
+ AddContextMenuHandlerCommon(kRootKeyNameForFile);
+ // AddContextMenuHandlerCommon(kRootKeyNameForFolder);
+ AddContextMenuHandlerCommon(kRootKeyNameForDirectory);
+
+ AddDragDropMenuHandlerCommon(kRootKeyNameForDirectory);
+ AddDragDropMenuHandlerCommon(kRootKeyNameForDrive);
+}
+
+}
diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.h b/CPP/7zip/UI/Explorer/RegistryContextMenu.h
new file mode 100755
index 00000000..52b053da
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.h
@@ -0,0 +1,13 @@
+// RegistryContextMenu.h
+
+#ifndef __REGISTRYCONTEXTMENU_H
+#define __REGISTRYCONTEXTMENU_H
+
+namespace NZipRootRegistry {
+
+ bool CheckContextMenuHandler();
+ void AddContextMenuHandler();
+ void DeleteContextMenuHandler();
+}
+
+#endif
diff --git a/CPP/7zip/UI/Explorer/StdAfx.cpp b/CPP/7zip/UI/Explorer/StdAfx.cpp
new file mode 100755
index 00000000..2550270c
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "stdafx.h"
diff --git a/CPP/7zip/UI/Explorer/StdAfx.h b/CPP/7zip/UI/Explorer/StdAfx.h
new file mode 100755
index 00000000..b9c0ee3a
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/StdAfx.h
@@ -0,0 +1,26 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#define _WIN32_WINNT 0x0400
+// it's hack for Windows NT supporting
+#define WINVER 0x0400
+
+// #define _WIN32_IE 0x0500
+#include <windows.h>
+#include <CommCtrl.h>
+#include <shlobj.h>
+#include <tchar.h>
+
+#include <stddef.h>
+#include <string.h>
+#include <mbstring.h>
+#include <wchar.h>
+
+#include <shlguid.h>
+#include <regstr.h>
+
+#include "Common/NewHandler.h"
+
+#endif
diff --git a/CPP/7zip/UI/Explorer/SystemPage/SystemPage.cpp b/CPP/7zip/UI/Explorer/SystemPage/SystemPage.cpp
new file mode 100755
index 00000000..cc2f974d
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/SystemPage/SystemPage.cpp
@@ -0,0 +1,212 @@
+// SystemPage.cpp
+
+#include "StdAfx.h"
+#include "resource.h"
+#include "../resource.h"
+
+#include "Common/StringConvert.h"
+#include "Windows/Defs.h"
+#include "Windows/Control/ListView.h"
+
+#include "SystemPage.h"
+
+#include "../../Common/ZipRegistry.h"
+#include "../RegistryContextMenu.h"
+#include "../ContextMenuFlags.h"
+
+#include "../../../FileManager/HelpUtils.h"
+#include "../../../FileManager/LangUtils.h"
+#include "../../../FileManager/FormatUtils.h"
+
+using namespace NContextMenuFlags;
+
+static CIDLangPair kIDLangPairs[] =
+{
+ { IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, 0x01000301},
+ { IDC_SYSTEM_CASCADED_MENU, 0x01000302},
+ { IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS, 0x01000310}
+};
+
+static LPCWSTR kSystemTopic = L"fm/plugins/7-zip/options.htm#system";
+
+struct CContextMenuItem
+{
+ int ControlID;
+ UINT32 LangID;
+ UINT32 Flag;
+};
+
+static CContextMenuItem kMenuItems[] =
+{
+ { IDS_CONTEXT_OPEN, 0x02000103, kOpen},
+ { IDS_CONTEXT_EXTRACT, 0x02000105, kExtract},
+ { IDS_CONTEXT_EXTRACT_HERE, 0x0200010B, kExtractHere },
+ { IDS_CONTEXT_EXTRACT_TO, 0x0200010D, kExtractTo },
+
+ { IDS_CONTEXT_TEST, 0x02000109, kTest},
+
+ { IDS_CONTEXT_COMPRESS, 0x02000107, kCompress },
+ { IDS_CONTEXT_COMPRESS_EMAIL, 0x02000111, kCompressEmail },
+ { IDS_CONTEXT_COMPRESS_TO, 0x0200010F, kCompressTo7z },
+ { IDS_CONTEXT_COMPRESS_TO_EMAIL, 0x02000113, kCompressTo7zEmail},
+ { IDS_CONTEXT_COMPRESS_TO, 0x0200010F, kCompressToZip },
+ { IDS_CONTEXT_COMPRESS_TO_EMAIL, 0x02000113, kCompressToZipEmail},
+};
+
+const int kNumMenuItems = sizeof(kMenuItems) / sizeof(kMenuItems[0]);
+
+bool CSystemPage::OnInit()
+{
+ _initMode = true;
+ LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));
+
+ CheckButton(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU,
+ NZipRootRegistry::CheckContextMenuHandler());
+
+ CheckButton(IDC_SYSTEM_CASCADED_MENU, ReadCascadedMenu());
+
+ UINT32 contextMenuFlags;
+ if (!ReadContextMenuStatus(contextMenuFlags))
+ contextMenuFlags = NContextMenuFlags::GetDefaultFlags();
+
+ m_ListView.Attach(GetItem(IDC_SYSTEM_OPTIONS_LIST));
+
+ /*
+ CheckButton(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU,
+ NRegistryAssociations::CheckContextMenuHandler());
+ */
+
+ UINT32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT;
+ m_ListView.SetExtendedListViewStyle(newFlags, newFlags);
+
+ UString s; // = TEXT("Items"); // LangLoadString(IDS_PROPERTY_EXTENSION, 0x02000205);
+ LVCOLUMNW column;
+ column.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT | LVCF_SUBITEM;
+ column.cx = 270;
+ column.fmt = LVCFMT_LEFT;
+ column.pszText = (LPWSTR)(LPCWSTR)s;
+ column.iSubItem = 0;
+ m_ListView.InsertColumn(0, &column);
+
+ for (int i = 0; i < kNumMenuItems; i++)
+ {
+ CContextMenuItem &menuItem = kMenuItems[i];
+ LVITEMW item;
+ item.iItem = i;
+ item.mask = LVIF_TEXT | LVIF_PARAM;
+ item.lParam = i;
+
+ UString s = LangString(menuItem.ControlID, menuItem.LangID);
+
+ switch(menuItem.ControlID)
+ {
+ case IDS_CONTEXT_EXTRACT_TO:
+ {
+ s = MyFormatNew(s, LangString(IDS_CONTEXT_FOLDER, 0x02000140));
+ break;
+ }
+ case IDS_CONTEXT_COMPRESS_TO:
+ case IDS_CONTEXT_COMPRESS_TO_EMAIL:
+ {
+ UString s2 = LangString(IDS_CONTEXT_ARCHIVE, 0x02000141);
+ switch(menuItem.Flag)
+ {
+ case kCompressTo7z:
+ case kCompressTo7zEmail:
+ s2 += L".7z";
+ break;
+ case kCompressToZip:
+ case kCompressToZipEmail:
+ s2 += L".zip";
+ break;
+ }
+ s = MyFormatNew(s, s2);
+ break;
+ }
+ }
+
+ // UString MyFormatNew(const UString &format, const UString &argument);
+
+ item.pszText = (LPWSTR)(LPCWSTR)s;
+ item.iSubItem = 0;
+ int itemIndex = m_ListView.InsertItem(&item);
+ m_ListView.SetCheckState(itemIndex, ((contextMenuFlags & menuItem.Flag) != 0));
+ }
+
+ _initMode = false;
+ return CPropertyPage::OnInit();
+}
+
+STDAPI DllRegisterServer(void);
+STDAPI DllUnregisterServer(void);
+
+LONG CSystemPage::OnApply()
+{
+ if (IsButtonCheckedBool(IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU))
+ {
+ DllRegisterServer();
+ NZipRootRegistry::AddContextMenuHandler();
+ }
+ else
+ {
+ DllUnregisterServer();
+ NZipRootRegistry::DeleteContextMenuHandler();
+ }
+ SaveCascadedMenu(IsButtonCheckedBool(IDC_SYSTEM_CASCADED_MENU));
+
+ UINT32 flags = 0;
+ for (int i = 0; i < kNumMenuItems; i++)
+ if (m_ListView.GetCheckState(i))
+ flags |= kMenuItems[i].Flag;
+ SaveContextMenuStatus(flags);
+
+ return PSNRET_NOERROR;
+}
+
+void CSystemPage::OnNotifyHelp()
+{
+ ShowHelpWindow(NULL, kSystemTopic);
+}
+
+bool CSystemPage::OnButtonClicked(int buttonID, HWND buttonHWND)
+{
+ switch(buttonID)
+ {
+ case IDC_SYSTEM_CASCADED_MENU:
+ case IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU:
+ Changed();
+ return true;
+ }
+ return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
+
+}
+
+bool CSystemPage::OnNotify(UINT aControlID, LPNMHDR lParam)
+{
+ if (lParam->hwndFrom == HWND(m_ListView))
+ {
+ switch(lParam->code)
+ {
+ case (LVN_ITEMCHANGED):
+ return OnItemChanged((const NMLISTVIEW *)lParam);
+ }
+ }
+ return CPropertyPage::OnNotify(aControlID, lParam);
+}
+
+
+bool CSystemPage::OnItemChanged(const NMLISTVIEW *info)
+{
+ if (_initMode)
+ return true;
+ if ((info->uChanged & LVIF_STATE) != 0)
+ {
+ UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK;
+ UINT newState = info->uNewState & LVIS_STATEIMAGEMASK;
+ if (oldState != newState)
+ Changed();
+ }
+ // PostMessage(kRefreshpluginsListMessage, 0);
+ // RefreshPluginsList();
+ return true;
+}
diff --git a/CPP/7zip/UI/Explorer/SystemPage/SystemPage.h b/CPP/7zip/UI/Explorer/SystemPage/SystemPage.h
new file mode 100755
index 00000000..a7de7c79
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/SystemPage/SystemPage.h
@@ -0,0 +1,25 @@
+// SystemPage.h
+
+#ifndef __SYSTEMPAGE_H
+#define __SYSTEMPAGE_H
+
+#include "Windows/Control/PropertyPage.h"
+#include "Windows/Control/ListView.h"
+
+#include "../../Common/ArchiverInfo.h"
+
+class CSystemPage: public NWindows::NControl::CPropertyPage
+{
+ bool _initMode;
+ CObjectVector<CArchiverInfo> m_Archivers;
+ NWindows::NControl::CListView m_ListView;
+public:
+ virtual bool OnInit();
+ virtual void OnNotifyHelp();
+ virtual bool OnNotify(UINT aControlID, LPNMHDR lParam);
+ virtual bool OnItemChanged(const NMLISTVIEW *info);
+ virtual LONG OnApply();
+ virtual bool OnButtonClicked(int aButtonID, HWND aButtonHWND);
+};
+
+#endif
diff --git a/CPP/7zip/UI/Explorer/SystemPage/resource.h b/CPP/7zip/UI/Explorer/SystemPage/resource.h
new file mode 100755
index 00000000..b125849c
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/SystemPage/resource.h
@@ -0,0 +1,6 @@
+#define IDD_SYSTEM 102
+
+#define IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU 1010
+#define IDC_SYSTEM_CASCADED_MENU 1011
+#define IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS 1020
+#define IDC_SYSTEM_OPTIONS_LIST 1022
diff --git a/CPP/7zip/UI/Explorer/SystemPage/resource.rc b/CPP/7zip/UI/Explorer/SystemPage/resource.rc
new file mode 100755
index 00000000..fdfed433
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/SystemPage/resource.rc
@@ -0,0 +1,24 @@
+#include "resource.h"
+#include "../../../GuiCommon.rc"
+
+#define xSize2 196
+#define ySize2 164
+#define xSize (xSize2 + marg + marg)
+#define ySize (ySize2 + marg + marg)
+
+IDD_SYSTEM DIALOG 0, 0, xSize, ySize MY_PAGE_STYLE
+CAPTION "System"
+MY_FONT
+BEGIN
+ CONTROL "Integrate 7-Zip to shell context menu", IDC_SYSTEM_INTEGRATE_TO_CONTEXT_MENU,
+ "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
+ marg, marg, xSize2, 10
+ CONTROL "Cascaded context menu", IDC_SYSTEM_CASCADED_MENU,
+ "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
+ marg, 21, xSize2, 10
+ LTEXT "Context menu items:", IDC_SYSTEM_STATIC_CONTEXT_MENU_ITEMS,
+ marg, 37, xSize2, 8
+ CONTROL "List1", IDC_SYSTEM_OPTIONS_LIST, "SysListView32",
+ LVS_REPORT | LVS_SINGLESEL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,
+ marg, 50, xSize2, ySize - marg - 50
+END
diff --git a/CPP/7zip/UI/Explorer/makefile b/CPP/7zip/UI/Explorer/makefile
new file mode 100755
index 00000000..0fcc57e4
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/makefile
@@ -0,0 +1,137 @@
+PROG = 7-zip.dll
+DEF_FILE = Explorer.def
+LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib htmlhelp.lib shell32.lib comctl32.lib ole32.lib comdlg32.lib
+CFLAGS = $(CFLAGS) -I ../../../ \
+ -DLANG \
+ -DNEW_FOLDER_INTERFACE \
+ -DWIN_LONG_PATH
+
+EXPLORER_OBJS = \
+ $O\DllExports.obj \
+ $O\ContextMenu.obj \
+ $O\MyMessages.obj \
+ $O\OptionsDialog.obj \
+ $O\RegistryContextMenu.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\IntToString.obj \
+ $O\Lang.obj \
+ $O\ListFileUtils.obj \
+ $O\NewHandler.obj \
+ $O\Random.obj \
+ $O\StdInStream.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\TextConfig.obj \
+ $O\UTFConvert.obj \
+ $O\Vector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\Error.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileName.obj \
+ $O\Menu.obj \
+ $O\PropVariant.obj \
+ $O\PropVariantConversions.obj \
+ $O\Registry.obj \
+ $O\ResourceString.obj \
+ $O\Shell.obj \
+ $O\Synchronization.obj \
+ $O\Window.obj \
+
+WIN_CTRL_OBJS = \
+ $O\Dialog.obj \
+ $O\PropertyPage.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\FilePathAutoRename.obj \
+ $O\FileStreams.obj \
+ $O\StreamUtils.obj \
+
+UI_COMMON_OBJS = \
+ $O\ArchiveExtractCallback.obj \
+ $O\ArchiveName.obj \
+ $O\ArchiveOpenCallback.obj \
+ $O\ArchiverInfo.obj \
+ $O\CompressCall.obj \
+ $O\DefaultName.obj \
+ $O\EnumDirItems.obj \
+ $O\ExtractingFilePath.obj \
+ $O\OpenArchive.obj \
+ $O\PropIDUtils.obj \
+ $O\SortUtils.obj \
+ $O\UpdateAction.obj \
+ $O\UpdateCallback.obj \
+ $O\UpdatePair.obj \
+ $O\UpdateProduce.obj \
+ $O\WorkDir.obj \
+ $O\ZipRegistry.obj \
+
+AGENT_OBJS = \
+ $O\Agent.obj \
+ $O\AgentOut.obj \
+ $O\AgentProxy.obj \
+ $O\ArchiveFolder.obj \
+ $O\ArchiveFolderOpen.obj \
+ $O\ArchiveFolderOut.obj \
+ $O\UpdateCallbackAgent.obj \
+
+
+FM_COMMON_OBJS = \
+ $O\FormatUtils.obj \
+ $O\HelpUtils.obj \
+ $O\LangUtils.obj \
+ $O\ProgramLocation.obj \
+ $O\RegistryUtils.obj \
+
+C_OBJS = \
+ $O\Sort.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(EXPLORER_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(WIN_CTRL_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(UI_COMMON_OBJS) \
+ $(AGENT_OBJS) \
+ $(FM_COMMON_OBJS)\
+ $(C_OBJS) \
+ $O\SystemPage.obj \
+ $O\FoldersPage.obj \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(EXPLORER_OBJS): $(*B).cpp
+ $(COMPL)
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+ $(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+ $(COMPL)
+$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp
+ $(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+ $(COMPL)
+$(UI_COMMON_OBJS): ../Common/$(*B).cpp
+ $(COMPL)
+$(AGENT_OBJS): ../Agent/$(*B).cpp
+ $(COMPL)
+$(FM_COMMON_OBJS): ../../FileManager/$(*B).cpp
+ $(COMPL)
+$O\SystemPage.obj: SystemPage/$(*B).cpp
+ $(COMPL)
+$O\FoldersPage.obj: FoldersPage/$(*B).cpp
+ $(COMPL)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
+$(C_OBJS): ../../../../C/$(*B).c
+ $(COMPL_O2)
diff --git a/CPP/7zip/UI/Explorer/resource.h b/CPP/7zip/UI/Explorer/resource.h
new file mode 100755
index 00000000..aec1e7cd
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/resource.h
@@ -0,0 +1,31 @@
+#define IDS_CONTEXT_EXTRACT 42
+#define IDS_CONTEXT_EXTRACT_HELP 43
+#define IDS_CONTEXT_COMPRESS 44
+#define IDS_CONTEXT_COMPRESS_HELP 45
+#define IDS_CONTEXT_OPEN 46
+#define IDS_CONTEXT_OPEN_HELP 47
+#define IDS_CONTEXT_TEST 48
+#define IDS_CONTEXT_TEST_HELP 49
+#define IDS_CONTEXT_CAPTION_HELP 50
+#define IDS_CONTEXT_POPUP_CAPTION 51
+
+#define IDS_CONTEXT_EXTRACT_HERE 52
+#define IDS_CONTEXT_EXTRACT_HERE_HELP 53
+
+#define IDS_CONTEXT_EXTRACT_TO 54
+#define IDS_CONTEXT_EXTRACT_TO_HELP 55
+
+#define IDS_CONTEXT_COMPRESS_TO 56
+#define IDS_CONTEXT_COMPRESS_TO_HELP 57
+
+#define IDS_CONTEXT_COMPRESS_EMAIL 58
+#define IDS_CONTEXT_COMPRESS_EMAIL_HELP 59
+
+#define IDS_CONTEXT_COMPRESS_TO_EMAIL 60
+#define IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP 61
+
+#define IDS_CONTEXT_FOLDER 70
+#define IDS_CONTEXT_ARCHIVE 71
+
+#define IDS_ERROR 100
+#define IDS_CONFIG_DIALOG_CAPTION 102
diff --git a/CPP/7zip/UI/Explorer/resource.rc b/CPP/7zip/UI/Explorer/resource.rc
new file mode 100755
index 00000000..bf7601d9
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/resource.rc
@@ -0,0 +1,38 @@
+#include "../../MyVersionInfo.rc"
+#include "resource.h"
+
+MY_VERSION_INFO_DLL("7-Zip Shell Extension", "7-zip")
+
+1 24 "7-zip.dll.manifest"
+
+STRINGTABLE
+BEGIN
+ IDS_CONTEXT_EXTRACT "Extract files..."
+ IDS_CONTEXT_EXTRACT_HELP "Extracts files from the selected archive."
+ IDS_CONTEXT_COMPRESS "Add to archive..."
+ IDS_CONTEXT_COMPRESS_HELP "Adds the selected items to archive."
+ IDS_CONTEXT_OPEN "Open archive"
+ IDS_CONTEXT_OPEN_HELP "Opens the selected archive."
+ IDS_CONTEXT_TEST "Test archive"
+ IDS_CONTEXT_TEST_HELP "Tests integrity of the selected archive."
+ IDS_CONTEXT_CAPTION_HELP "7-Zip commands"
+ IDS_CONTEXT_POPUP_CAPTION "7-Zip"
+ IDS_CONTEXT_EXTRACT_HERE "Extract Here"
+ IDS_CONTEXT_EXTRACT_HERE_HELP "Extracts files from the selected archive to current folder."
+ IDS_CONTEXT_EXTRACT_TO "Extract to {0}"
+ IDS_CONTEXT_EXTRACT_TO_HELP "Extracts files to subfolder."
+ IDS_CONTEXT_COMPRESS_TO "Add to {0}"
+ IDS_CONTEXT_COMPRESS_TO_HELP "Adds the selected items to archive."
+ IDS_CONTEXT_COMPRESS_EMAIL "Compress and email..."
+ IDS_CONTEXT_COMPRESS_EMAIL_HELP "Compresses the selected items to archive and sends archive via email."
+ IDS_CONTEXT_COMPRESS_TO_EMAIL "Compress to {0} and email"
+ IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP "Compresses the selected items to archive and sends archive via email."
+ IDS_CONTEXT_FOLDER "<Folder>"
+ IDS_CONTEXT_ARCHIVE "<Archive>"
+ IDS_ERROR "Error"
+ IDS_CONFIG_DIALOG_CAPTION "7-Zip Options"
+END
+
+#include "FoldersPage/resource.rc"
+#include "SystemPage/resource.rc"
+
diff --git a/CPP/7zip/UI/Far/CLSIDConst.cpp b/CPP/7zip/UI/Far/CLSIDConst.cpp
new file mode 100755
index 00000000..a6cea92e
--- /dev/null
+++ b/CPP/7zip/UI/Far/CLSIDConst.cpp
@@ -0,0 +1,8 @@
+// CLSIDConst.cpp
+
+#include "StdAfx.h"
+
+#include <initguid.h>
+
+#include "../Agent/Agent.h"
+#include "../../IPassword.h"
diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp
new file mode 100755
index 00000000..e85df5e1
--- /dev/null
+++ b/CPP/7zip/UI/Far/ExtractEngine.cpp
@@ -0,0 +1,168 @@
+// ExtractEngine.h
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#include "ExtractEngine.h"
+
+#include "Common/Wildcard.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/Defs.h"
+
+#include "FarUtils.h"
+#include "Messages.h"
+#include "OverwriteDialog.h"
+
+using namespace NWindows;
+using namespace NFar;
+
+extern void PrintMessage(const char *message);
+
+CExtractCallBackImp::~CExtractCallBackImp()
+{
+}
+
+void CExtractCallBackImp::Init(
+ UINT codePage,
+ CProgressBox *progressBox,
+ bool passwordIsDefined,
+ const UString &password)
+{
+ m_PasswordIsDefined = passwordIsDefined;
+ m_Password = password;
+ m_CodePage = codePage;
+ m_ProgressBox = progressBox;
+}
+
+STDMETHODIMP CExtractCallBackImp::SetTotal(UINT64 size)
+{
+ if (m_ProgressBox != 0)
+ {
+ m_ProgressBox->SetTotal(size);
+ m_ProgressBox->PrintCompeteValue(0);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallBackImp::SetCompleted(const UINT64 *completeValue)
+{
+ if(WasEscPressed())
+ return E_ABORT;
+ if (m_ProgressBox != 0 && completeValue != NULL)
+ m_ProgressBox->PrintCompeteValue(*completeValue);
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallBackImp::AskOverwrite(
+ const wchar_t *existName, const FILETIME *existTime, const UINT64 *existSize,
+ const wchar_t *newName, const FILETIME *aNewTime, const UINT64 *newSize,
+ INT32 *answer)
+{
+ NOverwriteDialog::CFileInfo oldFileInfo, newFileInfo;
+ oldFileInfo.Time = *existTime;
+ oldFileInfo.SizeIsDefined = (existSize != NULL);
+ if (oldFileInfo.SizeIsDefined)
+ oldFileInfo.Size = *existSize;
+ oldFileInfo.Name = GetSystemString(existName, m_CodePage);
+
+
+ newFileInfo.Time = *aNewTime;
+
+ newFileInfo.SizeIsDefined = (newSize != NULL);
+ if (newFileInfo.SizeIsDefined)
+ newFileInfo.Size = *newSize;
+ newFileInfo.Name = GetSystemString(newName, m_CodePage);
+
+ NOverwriteDialog::NResult::EEnum result =
+ NOverwriteDialog::Execute(oldFileInfo, newFileInfo);
+
+ switch(result)
+ {
+ case NOverwriteDialog::NResult::kCancel:
+ // *answer = NOverwriteAnswer::kCancel;
+ // break;
+ return E_ABORT;
+ case NOverwriteDialog::NResult::kNo:
+ *answer = NOverwriteAnswer::kNo;
+ break;
+ case NOverwriteDialog::NResult::kNoToAll:
+ *answer = NOverwriteAnswer::kNoToAll;
+ break;
+ case NOverwriteDialog::NResult::kYesToAll:
+ *answer = NOverwriteAnswer::kYesToAll;
+ break;
+ case NOverwriteDialog::NResult::kYes:
+ *answer = NOverwriteAnswer::kYes;
+ break;
+ case NOverwriteDialog::NResult::kAutoRename:
+ *answer = NOverwriteAnswer::kAutoRename;
+ break;
+ default:
+ throw 20413;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallBackImp::PrepareOperation(const wchar_t *name, INT32 /* askExtractMode */, const UINT64 * /* position */)
+{
+ m_CurrentFilePath = name;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallBackImp::MessageError(const wchar_t *message)
+{
+ AString s = UnicodeStringToMultiByte(message, CP_OEMCP);
+ if (g_StartupInfo.ShowMessage((const char *)s) == -1)
+ return E_ABORT;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallBackImp::SetOperationResult(INT32 operationResult, bool encrypted)
+{
+ switch(operationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kOK:
+ break;
+ default:
+ {
+ UINT idMessage;
+ switch(operationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
+ idMessage = NMessageID::kExtractUnsupportedMethod;
+ break;
+ case NArchive::NExtract::NOperationResult::kCRCError:
+ idMessage = NMessageID::kExtractCRCFailed;
+ break;
+ case NArchive::NExtract::NOperationResult::kDataError:
+ idMessage = NMessageID::kExtractDataError;
+ break;
+ default:
+ return E_FAIL;
+ }
+ char buffer[512];
+ sprintf(buffer, g_StartupInfo.GetMsgString(idMessage),
+ GetSystemString(m_CurrentFilePath, m_CodePage));
+ if (g_StartupInfo.ShowMessage(buffer) == -1)
+ return E_ABORT;
+ }
+ }
+ return S_OK;
+}
+
+extern HRESULT GetPassword(UString &password);
+
+STDMETHODIMP CExtractCallBackImp::CryptoGetTextPassword(BSTR *password)
+{
+ if (!m_PasswordIsDefined)
+ {
+ RINOK(GetPassword(m_Password));
+ m_PasswordIsDefined = true;
+ }
+ CMyComBSTR tempName = m_Password;
+ *password = tempName.Detach();
+
+ return S_OK;
+}
diff --git a/CPP/7zip/UI/Far/ExtractEngine.h b/CPP/7zip/UI/Far/ExtractEngine.h
new file mode 100755
index 00000000..57c04f76
--- /dev/null
+++ b/CPP/7zip/UI/Far/ExtractEngine.h
@@ -0,0 +1,68 @@
+// ExtractEngine.h
+
+#ifndef __EXTRACTENGINE_H
+#define __EXTRACTENGINE_H
+
+#include "Common/MyCom.h"
+#include "Common/String.h"
+
+#include "../../IPassword.h"
+#include "../Agent/IFolderArchive.h"
+
+#include "ProgressBox.h"
+
+class CExtractCallBackImp:
+ public IFolderArchiveExtractCallback,
+ public ICryptoGetTextPassword,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
+
+ // IProgress
+ STDMETHOD(SetTotal)(UINT64 size);
+ STDMETHOD(SetCompleted)(const UINT64 *completeValue);
+
+ // IExtractCallBack
+ STDMETHOD(AskOverwrite)(
+ const wchar_t *existName, const FILETIME *existTime, const UINT64 *existSize,
+ const wchar_t *newName, const FILETIME *newTime, const UINT64 *newSize,
+ INT32 *result);
+ STDMETHOD (PrepareOperation)(const wchar_t *name, INT32 askExtractMode, const UINT64 *position);
+
+ STDMETHOD(MessageError)(const wchar_t *message);
+ STDMETHOD(SetOperationResult)(INT32 resultEOperationResult, bool encrypted);
+ // ICryptoGetTextPassword
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+
+private:
+ UString m_CurrentFilePath;
+
+ struct CProcessedFileInfo
+ {
+ FILETIME UTCLastWriteTime;
+ bool IsDirectory;
+ UINT32 Attributes;
+ } m_ProcessedFileInfo;
+
+ CProgressBox *m_ProgressBox;
+ UINT m_CodePage;
+
+ bool m_PasswordIsDefined;
+ UString m_Password;
+
+ void CreateComplexDirectory(const UStringVector &dirPathParts);
+ /*
+ void GetPropertyValue(LPITEMIDLIST anItemIDList, PROPID aPropId,
+ PROPVARIANT *aValue);
+ bool IsEncrypted(LPITEMIDLIST anItemIDList);
+ */
+ void AddErrorMessage(LPCTSTR message);
+public:
+ ~CExtractCallBackImp();
+ void Init(UINT codePage,
+ CProgressBox *progressBox,
+ bool passwordIsDefined, const UString &password);
+};
+
+#endif
diff --git a/CPP/7zip/UI/Far/Far.def b/CPP/7zip/UI/Far/Far.def
new file mode 100755
index 00000000..d96501e2
--- /dev/null
+++ b/CPP/7zip/UI/Far/Far.def
@@ -0,0 +1,20 @@
+; 7-ZipFar.def : Declares the module parameters for the DLL.
+
+LIBRARY "7-ZipFar"
+DESCRIPTION '7-ZipFar Windows Dynamic Link Library'
+
+EXPORTS
+ SetStartupInfo = _SetStartupInfo@4
+ OpenPlugin = _OpenPlugin@8
+ OpenFilePlugin = _OpenFilePlugin@12
+ ClosePlugin = _ClosePlugin@4
+ GetFindData = _GetFindData@16
+ FreeFindData = _FreeFindData@12
+ SetDirectory = _SetDirectory@12
+ GetPluginInfo = _GetPluginInfo@4
+ Configure = _Configure@4
+ GetOpenPluginInfo = _GetOpenPluginInfo@8
+ GetFiles = _GetFiles@24
+ PutFiles = _PutFiles@20
+ DeleteFiles = _DeleteFiles@16
+ ProcessKey = _ProcessKey@12
diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp
new file mode 100755
index 00000000..47c44c69
--- /dev/null
+++ b/CPP/7zip/UI/Far/Far.dsp
@@ -0,0 +1,561 @@
+# Microsoft Developer Studio Project File - Name="Far" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Far - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Far.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Far.mak" CFG="Far - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Far - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Far - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Far - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /Yu"StdAfx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Far - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\Far\Plugins\7-Zip\7-ZipFar.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Far - Win32 Release"
+# Name "Far - Win32 Debug"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\CLSIDConst.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Far.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\Alloc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Alloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "Plugin"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ExtractEngine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ExtractEngine.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Messages.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OverwriteDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OverwriteDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Plugin.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Plugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PluginDelete.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PluginRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PluginWrite.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\UpdateCallback100.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\UpdateCallback100.h
+# End Source File
+# End Group
+# Begin Group "Far"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\FarPlugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\FarUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\FarUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProgressBox.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProgressBox.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Error.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Registry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Registry.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.h
+# End Source File
+# End Group
+# Begin Group "UI Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\ArchiveExtractCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveOpenCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveOpenCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiverInfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiverInfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DefaultName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DefaultName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DirItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\EnumDirItems.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\EnumDirItems.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExtractingFilePath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExtractingFilePath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExtractMode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\HandlerLoader.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\OpenArchive.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\OpenArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\PropIDUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\PropIDUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SortUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SortUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateAction.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateAction.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdatePair.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdatePair.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateProduce.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateProduce.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\WorkDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\WorkDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ZipRegistry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ZipRegistry.h
+# End Source File
+# End Group
+# Begin Group "Agent"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Agent\Agent.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\Agent.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\AgentOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\AgentProxy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\AgentProxy.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\IFolderArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\UpdateCallbackAgent.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\UpdateCallbackAgent.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.h
+# End Source File
+# End Group
+# Begin Group "7-zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\FilePathAutoRename.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FilePathAutoRename.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/CPP/7zip/UI/Far/Far.dsw b/CPP/7zip/UI/Far/Far.dsw
new file mode 100755
index 00000000..f4ef0801
--- /dev/null
+++ b/CPP/7zip/UI/Far/Far.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Far"=.\Far.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/UI/Far/FarPlugin.h b/CPP/7zip/UI/Far/FarPlugin.h
new file mode 100755
index 00000000..f61bbcb4
--- /dev/null
+++ b/CPP/7zip/UI/Far/FarPlugin.h
@@ -0,0 +1,577 @@
+// FarPlugin.h
+
+#ifndef __FARPLUGIN_H
+#define __FARPLUGIN_H
+
+#if defined(__BORLANDC__) && (__BORLANDC <= 0x520)
+ #pragma option -a1
+#elif defined(__GNUC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1100))
+ #pragma pack(1)
+#else
+ #pragma pack(push,1)
+ #if _MSC_VER
+ #define _export
+ #endif
+#endif
+
+#define NM 260
+
+struct FarFindData
+{
+ DWORD dwFileAttributes;
+ FILETIME ftCreationTime;
+ FILETIME ftLastAccessTime;
+ FILETIME ftLastWriteTime;
+ DWORD nFileSizeHigh;
+ DWORD nFileSizeLow;
+ DWORD dwReserved0;
+ DWORD dwReserved1;
+ char cFileName[ MAX_PATH ];
+ char cAlternateFileName[ 14 ];
+};
+
+struct PluginPanelItem
+{
+ FarFindData FindData;
+ DWORD PackSizeHigh;
+ DWORD PackSize;
+ DWORD Flags;
+ DWORD NumberOfLinks;
+ char *Description;
+ char *Owner;
+ char **CustomColumnData;
+ int CustomColumnNumber;
+ DWORD UserData;
+ DWORD Reserved[3];
+};
+
+#define PPIF_PROCESSDESCR 0x80000000
+#define PPIF_SELECTED 0x40000000
+#define PPIF_USERDATA 0x20000000
+
+enum {
+ FMENU_SHOWAMPERSAND=1,
+ FMENU_WRAPMODE=2,
+ FMENU_AUTOHIGHLIGHT=4,
+ FMENU_REVERSEAUTOHIGHLIGHT=8
+};
+
+
+typedef int (WINAPI *FARAPIMENU)(
+ int PluginNumber,
+ int X,
+ int Y,
+ int MaxHeight,
+ unsigned int Flags,
+ char *Title,
+ char *Bottom,
+ char *HelpTopic,
+ int *BreakKeys,
+ int *BreakCode,
+ struct FarMenuItem *Item,
+ int ItemsNumber
+);
+
+typedef int (WINAPI *FARAPIDIALOG)(
+ int PluginNumber,
+ int X1,
+ int Y1,
+ int X2,
+ int Y2,
+ char *HelpTopic,
+ struct FarDialogItem *Item,
+ int ItemsNumber
+);
+
+enum {
+ FMSG_WARNING=1,
+ FMSG_ERRORTYPE=2,
+ FMSG_KEEPBACKGROUND=4,
+ FMSG_DOWN=8,
+ FMSG_LEFTALIGN=16
+};
+
+typedef int (WINAPI *FARAPIMESSAGE)(
+ int PluginNumber,
+ unsigned int Flags,
+ char *HelpTopic,
+ char **Items,
+ int ItemsNumber,
+ int ButtonsNumber
+);
+
+typedef char* (WINAPI *FARAPIGETMSG)(
+ int PluginNumber,
+ int MsgId
+);
+
+
+enum DialogItemTypes {
+ DI_TEXT,
+ DI_VTEXT,
+ DI_SINGLEBOX,
+ DI_DOUBLEBOX,
+ DI_EDIT,
+ DI_PSWEDIT,
+ DI_FIXEDIT,
+ DI_BUTTON,
+ DI_CHECKBOX,
+ DI_RADIOBUTTON
+};
+
+enum FarDialogItemFlags {
+ DIF_COLORMASK = 0xff,
+ DIF_SETCOLOR = 0x100,
+ DIF_BOXCOLOR = 0x200,
+ DIF_GROUP = 0x400,
+ DIF_LEFTTEXT = 0x800,
+ DIF_MOVESELECT = 0x1000,
+ DIF_SHOWAMPERSAND = 0x2000,
+ DIF_CENTERGROUP = 0x4000,
+ DIF_NOBRACKETS = 0x8000,
+ DIF_SEPARATOR = 0x10000,
+ DIF_EDITOR = 0x20000,
+ DIF_HISTORY = 0x40000
+};
+
+struct FarDialogItem
+{
+ int Type;
+ int X1,Y1,X2,Y2;
+ int Focus;
+ union
+ {
+ int Selected;
+ const char *History;
+ const char *Mask;
+ struct FarList *ListItems;
+ int ListPos;
+ CHAR_INFO *VBuf;
+ };
+ unsigned int Flags;
+ int DefaultButton;
+ char Data[512];
+};
+
+
+struct FarMenuItem
+{
+ char Text[128];
+ int Selected;
+ int Checked;
+ int Separator;
+};
+
+
+enum {FCTL_CLOSEPLUGIN,FCTL_GETPANELINFO,FCTL_GETANOTHERPANELINFO,
+ FCTL_UPDATEPANEL,FCTL_UPDATEANOTHERPANEL,
+ FCTL_REDRAWPANEL,FCTL_REDRAWANOTHERPANEL,
+ FCTL_SETANOTHERPANELDIR,FCTL_GETCMDLINE,FCTL_SETCMDLINE,
+ FCTL_SETSELECTION,FCTL_SETANOTHERSELECTION,
+ FCTL_SETVIEWMODE,FCTL_SETANOTHERVIEWMODE,FCTL_INSERTCMDLINE,
+ FCTL_SETUSERSCREEN,FCTL_SETPANELDIR,FCTL_SETCMDLINEPOS,
+ FCTL_GETCMDLINEPOS
+};
+
+enum {PTYPE_FILEPANEL,PTYPE_TREEPANEL,PTYPE_QVIEWPANEL,PTYPE_INFOPANEL};
+
+struct PanelInfo
+{
+ int PanelType;
+ int Plugin;
+ RECT PanelRect;
+ struct PluginPanelItem *PanelItems;
+ int ItemsNumber;
+ struct PluginPanelItem *SelectedItems;
+ int SelectedItemsNumber;
+ int CurrentItem;
+ int TopPanelItem;
+ int Visible;
+ int Focus;
+ int ViewMode;
+ char ColumnTypes[80];
+ char ColumnWidths[80];
+ char CurDir[NM];
+ int ShortNames;
+ int SortMode;
+ DWORD Reserved[2];
+};
+
+
+struct PanelRedrawInfo
+{
+ int CurrentItem;
+ int TopPanelItem;
+};
+
+
+typedef int (WINAPI *FARAPICONTROL)(
+ HANDLE hPlugin,
+ int Command,
+ void *Param
+);
+
+typedef HANDLE (WINAPI *FARAPISAVESCREEN)(int X1,int Y1,int X2,int Y2);
+
+typedef void (WINAPI *FARAPIRESTORESCREEN)(HANDLE hScreen);
+
+typedef int (WINAPI *FARAPIGETDIRLIST)(
+ char *Dir,
+ struct PluginPanelItem **pPanelItem,
+ int *pItemsNumber
+);
+
+typedef int (WINAPI *FARAPIGETPLUGINDIRLIST)(
+ int PluginNumber,
+ HANDLE hPlugin,
+ char *Dir,
+ struct PluginPanelItem **pPanelItem,
+ int *pItemsNumber
+);
+
+typedef void (WINAPI *FARAPIFREEDIRLIST)(struct PluginPanelItem *PanelItem);
+
+enum VIEWER_FLAGS {
+ VF_NONMODAL=1,VF_DELETEONCLOSE=2
+};
+
+typedef int (WINAPI *FARAPIVIEWER)(
+ char *FileName,
+ char *Title,
+ int X1,
+ int Y1,
+ int X2,
+ int Y2,
+ DWORD Flags
+);
+
+typedef int (WINAPI *FARAPIEDITOR)(
+ char *FileName,
+ char *Title,
+ int X1,
+ int Y1,
+ int X2,
+ int Y2,
+ DWORD Flags,
+ int StartLine,
+ int StartChar
+);
+
+typedef int (WINAPI *FARAPICMPNAME)(
+ char *Pattern,
+ char *String,
+ int SkipPath
+);
+
+
+#define FCT_DETECT 0x40000000
+
+struct CharTableSet
+{
+ char DecodeTable[256];
+ char EncodeTable[256];
+ char UpperTable[256];
+ char LowerTable[256];
+ char TableName[128];
+};
+
+typedef int (WINAPI *FARAPICHARTABLE)(
+ int Command,
+ char *Buffer,
+ int BufferSize
+);
+
+typedef void (WINAPI *FARAPITEXT)(
+ int X,
+ int Y,
+ int Color,
+ char *Str
+);
+
+
+typedef int (WINAPI *FARAPIEDITORCONTROL)(
+ int Command,
+ void *Param
+);
+
+
+enum EDITOR_EVENTS {
+ EE_READ,EE_SAVE,EE_REDRAW,EE_CLOSE
+};
+
+enum EDITOR_CONTROL_COMMANDS {
+ ECTL_GETSTRING,ECTL_SETSTRING,ECTL_INSERTSTRING,ECTL_DELETESTRING,
+ ECTL_DELETECHAR,ECTL_INSERTTEXT,ECTL_GETINFO,ECTL_SETPOSITION,
+ ECTL_SELECT,ECTL_REDRAW,ECTL_EDITORTOOEM,ECTL_OEMTOEDITOR,
+ ECTL_TABTOREAL,ECTL_REALTOTAB,ECTL_EXPANDTABS,ECTL_SETTITLE,
+ ECTL_READINPUT,ECTL_PROCESSINPUT,ECTL_ADDCOLOR,ECTL_GETCOLOR
+};
+
+
+struct EditorGetString
+{
+ int StringNumber;
+ char *StringText;
+ char *StringEOL;
+ int StringLength;
+ int SelStart;
+ int SelEnd;
+};
+
+
+struct EditorSetString
+{
+ int StringNumber;
+ char *StringText;
+ char *StringEOL;
+ int StringLength;
+};
+
+
+enum EDITOR_OPTIONS {
+ EOPT_EXPANDTABS=1,EOPT_PERSISTENTBLOCKS=2,EOPT_DELREMOVESBLOCKS=4,
+ EOPT_AUTOINDENT=8,EOPT_SAVEFILEPOSITION=16,EOPT_AUTODETECTTABLE=32,
+ EOPT_CURSORBEYONDEOL=64
+};
+
+
+enum EDITOR_BLOCK_TYPES {
+ BTYPE_NONE,BTYPE_STREAM,BTYPE_COLUMN
+};
+
+
+struct EditorInfo
+{
+ int EditorID;
+ char *FileName;
+ int WindowSizeX;
+ int WindowSizeY;
+ int TotalLines;
+ int CurLine;
+ int CurPos;
+ int CurTabPos;
+ int TopScreenLine;
+ int LeftPos;
+ int Overtype;
+ int BlockType;
+ int BlockStartLine;
+ int AnsiMode;
+ int TableNum;
+ DWORD Options;
+ int TabSize;
+ DWORD Reserved[8];
+};
+
+
+struct EditorSetPosition
+{
+ int CurLine;
+ int CurPos;
+ int CurTabPos;
+ int TopScreenLine;
+ int LeftPos;
+ int Overtype;
+};
+
+
+struct EditorSelect
+{
+ int BlockType;
+ int BlockStartLine;
+ int BlockStartPos;
+ int BlockWidth;
+ int BlockHeight;
+};
+
+
+struct EditorConvertText
+{
+ char *Text;
+ int TextLength;
+};
+
+
+struct EditorConvertPos
+{
+ int StringNumber;
+ int SrcPos;
+ int DestPos;
+};
+
+
+struct EditorColor
+{
+ int StringNumber;
+ int ColorItem;
+ int StartPos;
+ int EndPos;
+ int Color;
+};
+
+
+struct PluginStartupInfo
+{
+ int StructSize;
+ char ModuleName[NM];
+ int ModuleNumber;
+ char *RootKey;
+ FARAPIMENU Menu;
+ FARAPIDIALOG Dialog;
+ FARAPIMESSAGE Message;
+ FARAPIGETMSG GetMsg;
+ FARAPICONTROL Control;
+ FARAPISAVESCREEN SaveScreen;
+ FARAPIRESTORESCREEN RestoreScreen;
+ FARAPIGETDIRLIST GetDirList;
+ FARAPIGETPLUGINDIRLIST GetPluginDirList;
+ FARAPIFREEDIRLIST FreeDirList;
+ FARAPIVIEWER Viewer;
+ FARAPIEDITOR Editor;
+ FARAPICMPNAME CmpName;
+ FARAPICHARTABLE CharTable;
+ FARAPITEXT Text;
+ FARAPIEDITORCONTROL EditorControl;
+};
+
+
+enum PLUGIN_FLAGS {
+ PF_PRELOAD = 0x0001,
+ PF_DISABLEPANELS = 0x0002,
+ PF_EDITOR = 0x0004,
+ PF_VIEWER = 0x0008
+};
+
+
+struct PluginInfo
+{
+ int StructSize;
+ DWORD Flags;
+ char **DiskMenuStrings;
+ int *DiskMenuNumbers;
+ int DiskMenuStringsNumber;
+ char **PluginMenuStrings;
+ int PluginMenuStringsNumber;
+ char **PluginConfigStrings;
+ int PluginConfigStringsNumber;
+ char *CommandPrefix;
+};
+
+
+struct InfoPanelLine
+{
+ char Text[80];
+ char Data[80];
+ int Separator;
+};
+
+
+struct PanelMode
+{
+ char *ColumnTypes;
+ char *ColumnWidths;
+ char **ColumnTitles;
+ int FullScreen;
+ int DetailedStatus;
+ int AlignExtensions;
+ int CaseConversion;
+ char *StatusColumnTypes;
+ char *StatusColumnWidths;
+ DWORD Reserved[2];
+};
+
+
+enum OPENPLUGININFO_FLAGS {
+ OPIF_USEFILTER = 0x0001,
+ OPIF_USESORTGROUPS = 0x0002,
+ OPIF_USEHIGHLIGHTING = 0x0004,
+ OPIF_ADDDOTS = 0x0008,
+ OPIF_RAWSELECTION = 0x0010,
+ OPIF_REALNAMES = 0x0020,
+ OPIF_SHOWNAMESONLY = 0x0040,
+ OPIF_SHOWRIGHTALIGNNAMES = 0x0080,
+ OPIF_SHOWPRESERVECASE = 0x0100,
+ OPIF_FINDFOLDERS = 0x0200,
+ OPIF_COMPAREFATTIME = 0x0400,
+ OPIF_EXTERNALGET = 0x0800,
+ OPIF_EXTERNALPUT = 0x1000,
+ OPIF_EXTERNALDELETE = 0x2000,
+ OPIF_EXTERNALMKDIR = 0x4000,
+ OPIF_USEATTRHIGHLIGHTING = 0x8000
+};
+
+
+enum OPENPLUGININFO_SORTMODES {
+ SM_DEFAULT,SM_UNSORTED,SM_NAME,SM_EXT,SM_MTIME,SM_CTIME,
+ SM_ATIME,SM_SIZE,SM_DESCR,SM_OWNER,SM_COMPRESSEDSIZE,SM_NUMLINKS
+};
+
+
+struct KeyBarTitles
+{
+ char *Titles[12];
+ char *CtrlTitles[12];
+ char *AltTitles[12];
+ char *ShiftTitles[12];
+};
+
+
+struct OpenPluginInfo
+{
+ int StructSize;
+ DWORD Flags;
+ char *HostFile;
+ char *CurDir;
+ char *Format;
+ char *PanelTitle;
+ struct InfoPanelLine *InfoLines;
+ int InfoLinesNumber;
+ char **DescrFiles;
+ int DescrFilesNumber;
+ struct PanelMode *PanelModesArray;
+ int PanelModesNumber;
+ int StartPanelMode;
+ int StartSortMode;
+ int StartSortOrder;
+ struct KeyBarTitles *KeyBar;
+ char *ShortcutData;
+};
+
+enum {
+ OPEN_DISKMENU,
+ OPEN_PLUGINSMENU,
+ OPEN_FINDLIST,
+ OPEN_SHORTCUT,
+ OPEN_COMMANDLINE,
+ OPEN_EDITOR,
+ OPEN_VIEWER
+};
+
+enum {PKF_CONTROL=1,PKF_ALT=2,PKF_SHIFT=4};
+
+enum FAR_EVENTS {
+ FE_CHANGEVIEWMODE,
+ FE_REDRAW,
+ FE_IDLE,
+ FE_CLOSE,
+ FE_BREAK,
+ FE_COMMAND
+};
+
+enum OPERATION_MODES {
+ OPM_SILENT=1,
+ OPM_FIND=2,
+ OPM_VIEW=4,
+ OPM_EDIT=8,
+ OPM_TOPLEVEL=16,
+ OPM_DESCR=32
+};
+
+#if defined(__BORLANDC__) && (__BORLANDC <= 0x520)
+ #pragma option -a.
+#elif defined(__GNUC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1100))
+ #pragma pack()
+#else
+ #pragma pack(pop)
+#endif
+
+#endif
diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp
new file mode 100755
index 00000000..abbb6817
--- /dev/null
+++ b/CPP/7zip/UI/Far/FarUtils.cpp
@@ -0,0 +1,416 @@
+// FarUtils.cpp
+
+#include "StdAfx.h"
+
+#include "FarUtils.h"
+#include "Common/DynamicBuffer.h"
+#include "Common/StringConvert.h"
+#include "Windows/Defs.h"
+#include "Windows/Console.h"
+#include "Windows/Error.h"
+
+using namespace NWindows;
+
+namespace NFar {
+
+CStartupInfo g_StartupInfo;
+
+void CStartupInfo::Init(const PluginStartupInfo &pluginStartupInfo,
+ const CSysString &pliginNameForRegestry)
+{
+ m_Data = pluginStartupInfo;
+ m_RegistryPath = pluginStartupInfo.RootKey;
+ m_RegistryPath += '\\';
+ m_RegistryPath += pliginNameForRegestry;
+}
+
+const char *CStartupInfo::GetMsgString(int messageId)
+{
+ return (const char*)m_Data.GetMsg(m_Data.ModuleNumber, messageId);
+}
+
+int CStartupInfo::ShowMessage(unsigned int flags,
+ const char *helpTopic, const char **items, int numItems, int numButtons)
+{
+ return m_Data.Message(m_Data.ModuleNumber, flags, (char *)helpTopic,
+ (char **)items, numItems, numButtons);
+}
+
+namespace NMessageID
+{
+ enum
+ {
+ kOk,
+ kCancel,
+ kWarning,
+ kError
+ };
+}
+
+int CStartupInfo::ShowMessage(const char *message)
+{
+ const char *messagesItems[]= { GetMsgString(NMessageID::kError), message,
+ GetMsgString(NMessageID::kOk) };
+ return ShowMessage(FMSG_WARNING, NULL, messagesItems,
+ sizeof(messagesItems) / sizeof(messagesItems[0]), 1);
+}
+
+int CStartupInfo::ShowMessage(int messageId)
+{
+ return ShowMessage(GetMsgString(messageId));
+}
+
+int CStartupInfo::ShowDialog(int X1, int Y1, int X2, int Y2,
+ const char *helpTopic, struct FarDialogItem *items, int numItems)
+{
+ return m_Data.Dialog(m_Data.ModuleNumber, X1, Y1, X2, Y2, (char *)helpTopic,
+ items, numItems);
+}
+
+int CStartupInfo::ShowDialog(int sizeX, int sizeY,
+ const char *helpTopic, struct FarDialogItem *items, int numItems)
+{
+ return ShowDialog(-1, -1, sizeX, sizeY, helpTopic, items, numItems);
+}
+
+inline static BOOL GetBOOLValue(bool v) { return (v? TRUE: FALSE); }
+
+void CStartupInfo::InitDialogItems(const CInitDialogItem *srcItems,
+ FarDialogItem *destItems, int numItems)
+{
+ for (int i = 0; i < numItems; i++)
+ {
+ const CInitDialogItem &srcItem = srcItems[i];
+ FarDialogItem &destItem = destItems[i];
+
+ destItem.Type = srcItem.Type;
+ destItem.X1 = srcItem.X1;
+ destItem.Y1 = srcItem.Y1;
+ destItem.X2 = srcItem.X2;
+ destItem.Y2 = srcItem.Y2;
+ destItem.Focus = GetBOOLValue(srcItem.Focus);
+ if(srcItem.HistoryName != NULL)
+ destItem.History = srcItem.HistoryName;
+ else
+ destItem.Selected = GetBOOLValue(srcItem.Selected);
+ destItem.Flags = srcItem.Flags;
+ destItem.DefaultButton = GetBOOLValue(srcItem.DefaultButton);
+
+ if(srcItem.DataMessageId < 0)
+ MyStringCopy(destItem.Data, srcItem.DataString);
+ else
+ MyStringCopy(destItem.Data, GetMsgString(srcItem.DataMessageId));
+
+ /*
+ if ((unsigned int)Init[i].Data < 0xFFF)
+ MyStringCopy(destItem.Data, GetMsg((unsigned int)srcItem.Data));
+ else
+ MyStringCopy(destItem.Data,srcItem.Data);
+ */
+ }
+}
+
+// --------------------------------------------
+
+HANDLE CStartupInfo::SaveScreen(int X1, int Y1, int X2, int Y2)
+{
+ return m_Data.SaveScreen(X1, Y1, X2, Y2);
+}
+
+HANDLE CStartupInfo::SaveScreen()
+{
+ return SaveScreen(0, 0, -1, -1);
+}
+
+void CStartupInfo::RestoreScreen(HANDLE handle)
+{
+ m_Data.RestoreScreen(handle);
+}
+
+const char kRegestryKeyDelimiter = '\'';
+
+CSysString CStartupInfo::GetFullKeyName(const CSysString &keyName) const
+{
+ return (keyName.IsEmpty()) ? m_RegistryPath:
+ (m_RegistryPath + kRegestryKeyDelimiter + keyName);
+}
+
+
+LONG CStartupInfo::CreateRegKey(HKEY parentKey,
+ const CSysString &keyName, NRegistry::CKey &destKey) const
+{
+ return destKey.Create(parentKey, GetFullKeyName(keyName));
+}
+
+LONG CStartupInfo::OpenRegKey(HKEY parentKey,
+ const CSysString &keyName, NRegistry::CKey &destKey) const
+{
+ return destKey.Open(parentKey, GetFullKeyName(keyName));
+}
+
+void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName,
+ LPCTSTR valueName, LPCTSTR value) const
+{
+ NRegistry::CKey regKey;
+ CreateRegKey(parentKey, keyName, regKey);
+ regKey.SetValue(valueName, value);
+}
+
+void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName,
+ LPCTSTR valueName, UINT32 value) const
+{
+ NRegistry::CKey regKey;
+ CreateRegKey(parentKey, keyName, regKey);
+ regKey.SetValue(valueName, value);
+}
+
+void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName,
+ LPCTSTR valueName, bool value) const
+{
+ NRegistry::CKey regKey;
+ CreateRegKey(parentKey, keyName, regKey);
+ regKey.SetValue(valueName, value);
+}
+
+CSysString CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,
+ LPCTSTR valueName, const CSysString &valueDefault) const
+{
+ NRegistry::CKey regKey;
+ if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS)
+ return valueDefault;
+
+ CSysString value;
+ if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
+ return valueDefault;
+
+ return value;
+}
+
+UINT32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,
+ LPCTSTR valueName, UINT32 valueDefault) const
+{
+ NRegistry::CKey regKey;
+ if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS)
+ return valueDefault;
+
+ UINT32 value;
+ if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
+ return valueDefault;
+
+ return value;
+}
+
+bool CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,
+ LPCTSTR valueName, bool valueDefault) const
+{
+ NRegistry::CKey regKey;
+ if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS)
+ return valueDefault;
+
+ bool value;
+ if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
+ return valueDefault;
+
+ return value;
+}
+
+bool CStartupInfo::Control(HANDLE pluginHandle, int command, void *param)
+{
+ return BOOLToBool(m_Data.Control(pluginHandle, command, param));
+}
+
+bool CStartupInfo::ControlRequestActivePanel(int command, void *param)
+{
+ return Control(INVALID_HANDLE_VALUE, command, param);
+}
+
+bool CStartupInfo::ControlGetActivePanelInfo(PanelInfo &panelInfo)
+{
+ return ControlRequestActivePanel(FCTL_GETPANELINFO, &panelInfo);
+}
+
+bool CStartupInfo::ControlSetSelection(const PanelInfo &panelInfo)
+{
+ return ControlRequestActivePanel(FCTL_SETSELECTION, (void *)&panelInfo);
+}
+
+bool CStartupInfo::ControlGetActivePanelCurrentItemInfo(
+ PluginPanelItem &pluginPanelItem)
+{
+ PanelInfo panelInfo;
+ if(!ControlGetActivePanelInfo(panelInfo))
+ return false;
+ if(panelInfo.ItemsNumber <= 0)
+ throw "There are no items";
+ pluginPanelItem = panelInfo.PanelItems[panelInfo.CurrentItem];
+ return true;
+}
+
+bool CStartupInfo::ControlGetActivePanelSelectedOrCurrentItems(
+ CObjectVector<PluginPanelItem> &pluginPanelItems)
+{
+ pluginPanelItems.Clear();
+ PanelInfo panelInfo;
+ if(!ControlGetActivePanelInfo(panelInfo))
+ return false;
+ if(panelInfo.ItemsNumber <= 0)
+ throw "There are no items";
+ if (panelInfo.SelectedItemsNumber == 0)
+ pluginPanelItems.Add(panelInfo.PanelItems[panelInfo.CurrentItem]);
+ else
+ for (int i = 0; i < panelInfo.SelectedItemsNumber; i++)
+ pluginPanelItems.Add(panelInfo.SelectedItems[i]);
+ return true;
+}
+
+bool CStartupInfo::ControlClearPanelSelection()
+{
+ PanelInfo panelInfo;
+ if(!ControlGetActivePanelInfo(panelInfo))
+ return false;
+ for (int i = 0; i < panelInfo.ItemsNumber; i++)
+ panelInfo.PanelItems[i].Flags &= ~PPIF_SELECTED;
+ return ControlSetSelection(panelInfo);
+}
+
+////////////////////////////////////////////////
+// menu function
+
+int CStartupInfo::Menu(
+ int x,
+ int y,
+ int maxHeight,
+ unsigned int flags,
+ const char *title,
+ const char *aBottom,
+ const char *helpTopic,
+ int *breakKeys,
+ int *breakCode,
+ struct FarMenuItem *items,
+ int numItems)
+{
+ return m_Data.Menu(m_Data.ModuleNumber, x, y, maxHeight, flags, (char *)title,
+ (char *)aBottom, (char *)helpTopic, breakKeys, breakCode, items, numItems);
+}
+
+int CStartupInfo::Menu(
+ unsigned int flags,
+ const char *title,
+ const char *helpTopic,
+ struct FarMenuItem *items,
+ int numItems)
+{
+ return Menu(-1, -1, 0, flags, title, NULL, helpTopic, NULL,
+ NULL, items, numItems);
+}
+
+int CStartupInfo::Menu(
+ unsigned int flags,
+ const char *title,
+ const char *helpTopic,
+ const CSysStringVector &items,
+ int selectedItem)
+{
+ CRecordVector<FarMenuItem> farMenuItems;
+ for(int i = 0; i < items.Size(); i++)
+ {
+ FarMenuItem item;
+ item.Checked = 0;
+ item.Separator = 0;
+ item.Selected = (i == selectedItem);
+ AString reducedString = items[i].Left(sizeof(item.Text) / sizeof(item.Text[0]) - 1);
+ MyStringCopy(item.Text, (const char *)reducedString);
+ farMenuItems.Add(item);
+ }
+ return Menu(flags, title, helpTopic, &farMenuItems.Front(), farMenuItems.Size());
+}
+
+
+//////////////////////////////////
+// CScreenRestorer
+
+CScreenRestorer::~CScreenRestorer()
+{
+ Restore();
+}
+void CScreenRestorer::Save()
+{
+ if(m_Saved)
+ return;
+ m_HANDLE = g_StartupInfo.SaveScreen();
+ m_Saved = true;
+}
+
+void CScreenRestorer::Restore()
+{
+ if(m_Saved)
+ {
+ g_StartupInfo.RestoreScreen(m_HANDLE);
+ m_Saved = false;
+ }
+};
+
+static AString DWORDToString(DWORD number)
+{
+ char buffer[32];
+ ultoa(number, buffer, 10);
+ return buffer;
+}
+
+void PrintErrorMessage(const char *message, int code)
+{
+ CSysString tmp = message;
+ tmp += " #";
+ tmp += DWORDToString(code);
+ g_StartupInfo.ShowMessage(tmp);
+}
+
+void PrintErrorMessage(const char *message, const char *text)
+{
+ CSysString tmp = message;
+ tmp += ": ";
+ tmp += text;
+ g_StartupInfo.ShowMessage(tmp);
+}
+
+bool WasEscPressed()
+{
+ NConsole::CIn inConsole;
+ HANDLE handle = ::GetStdHandle(STD_INPUT_HANDLE);
+ if(handle == INVALID_HANDLE_VALUE)
+ return true;
+ inConsole.Attach(handle);
+ for (;;)
+ {
+ DWORD numEvents;
+ if(!inConsole.GetNumberOfEvents(numEvents))
+ return true;
+ if(numEvents == 0)
+ return false;
+
+ INPUT_RECORD event;
+ if(!inConsole.ReadEvent(event, numEvents))
+ return true;
+ if (event.EventType == KEY_EVENT &&
+ event.Event.KeyEvent.bKeyDown &&
+ event.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)
+ return true;
+ }
+}
+
+void ShowErrorMessage(DWORD errorCode)
+{
+ AString message;
+ NError::MyFormatMessage(errorCode, message);
+ message.Replace("\x0D", "");
+ message.Replace("\x0A", " ");
+ g_StartupInfo.ShowMessage(SystemStringToOemString(message));
+
+}
+
+void ShowLastErrorMessage()
+{
+ ShowErrorMessage(::GetLastError());
+}
+
+}
diff --git a/CPP/7zip/UI/Far/FarUtils.h b/CPP/7zip/UI/Far/FarUtils.h
new file mode 100755
index 00000000..4fba193d
--- /dev/null
+++ b/CPP/7zip/UI/Far/FarUtils.h
@@ -0,0 +1,185 @@
+// FarUtils.h
+
+#ifndef __FARUTILS_H
+#define __FARUTILS_H
+
+#include "FarPlugin.h"
+#include "Common/String.h"
+#include "Common/Vector.h"
+#include "Windows/Registry.h"
+
+namespace NFar {
+
+namespace NFileOperationReturnCode
+{
+ enum EEnum
+ {
+ kInterruptedByUser = -1,
+ kError = 0,
+ kSuccess = 1
+ };
+}
+
+namespace NEditorReturnCode
+{
+ enum EEnum
+ {
+ kOpenError = 0,
+ kFileWasChanged = 1,
+ kFileWasNotChanged = 2,
+ kInterruptedByUser = 3
+ };
+}
+
+struct CInitDialogItem
+{
+ DialogItemTypes Type;
+ int X1,Y1,X2,Y2;
+ bool Focus;
+ bool Selected;
+ unsigned int Flags; //FarDialogItemFlags Flags;
+ bool DefaultButton;
+ int DataMessageId;
+ const char *DataString;
+ const char *HistoryName;
+ // void InitToFarDialogItem(struct FarDialogItem &anItemDest);
+};
+
+class CStartupInfo
+{
+ PluginStartupInfo m_Data;
+ CSysString m_RegistryPath;
+
+ CSysString GetFullKeyName(const CSysString &keyName) const;
+ LONG CreateRegKey(HKEY parentKey,
+ const CSysString &keyName, NWindows::NRegistry::CKey &destKey) const;
+ LONG OpenRegKey(HKEY parentKey,
+ const CSysString &keyName, NWindows::NRegistry::CKey &destKey) const;
+
+public:
+ void Init(const PluginStartupInfo &pluginStartupInfo,
+ const CSysString &pliginNameForRegestry);
+ const char *GetMsgString(int messageId);
+ int ShowMessage(unsigned int flags, const char *helpTopic,
+ const char **items, int numItems, int numButtons);
+ int ShowMessage(const char *message);
+ int ShowMessage(int messageId);
+
+ int ShowDialog(int X1, int Y1, int X2, int Y2,
+ const char *helpTopic, struct FarDialogItem *items, int numItems);
+ int ShowDialog(int sizeX, int sizeY,
+ const char *helpTopic, struct FarDialogItem *items, int numItems);
+
+ void InitDialogItems(const CInitDialogItem *srcItems,
+ FarDialogItem *destItems, int numItems);
+
+ HANDLE SaveScreen(int X1, int Y1, int X2, int Y2);
+ HANDLE SaveScreen();
+ void RestoreScreen(HANDLE handle);
+
+ void SetRegKeyValue(HKEY parentKey, const CSysString &keyName,
+ const LPCTSTR valueName, LPCTSTR value) const;
+ void SetRegKeyValue(HKEY hRoot, const CSysString &keyName,
+ const LPCTSTR valueName, UINT32 value) const;
+ void SetRegKeyValue(HKEY hRoot, const CSysString &keyName,
+ const LPCTSTR valueName, bool value) const;
+
+ CSysString QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,
+ LPCTSTR valueName, const CSysString &valueDefault) const;
+
+ UINT32 QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,
+ LPCTSTR valueName, UINT32 valueDefault) const;
+
+ bool QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,
+ LPCTSTR valueName, bool valueDefault) const;
+
+ bool Control(HANDLE plugin, int command, void *param);
+ bool ControlRequestActivePanel(int command, void *param);
+ bool ControlGetActivePanelInfo(PanelInfo &panelInfo);
+ bool ControlSetSelection(const PanelInfo &panelInfo);
+ bool ControlGetActivePanelCurrentItemInfo(PluginPanelItem &pluginPanelItem);
+ bool ControlGetActivePanelSelectedOrCurrentItems(
+ CObjectVector<PluginPanelItem> &pluginPanelItems);
+
+ bool ControlClearPanelSelection();
+
+ int Menu(
+ int x,
+ int y,
+ int maxHeight,
+ unsigned int flags,
+ const char *title,
+ const char *aBottom,
+ const char *helpTopic,
+ int *breakKeys,
+ int *breakCode,
+ FarMenuItem *items,
+ int numItems);
+ int Menu(
+ unsigned int flags,
+ const char *title,
+ const char *helpTopic,
+ FarMenuItem *items,
+ int numItems);
+
+ int Menu(
+ unsigned int flags,
+ const char *title,
+ const char *helpTopic,
+ const CSysStringVector &items,
+ int selectedItem);
+
+ int Editor(const char *fileName, const char *title,
+ int X1, int Y1, int X2, int Y2, DWORD flags, int startLine, int startChar)
+ { return m_Data.Editor((char *)fileName, (char *)title, X1, Y1, X2, Y2,
+ flags, startLine, startChar); }
+ int Editor(const char *fileName)
+ { return Editor(fileName, NULL, 0, 0, -1, -1, 0, -1, -1); }
+
+ int Viewer(const char *fileName, const char *title,
+ int X1, int Y1, int X2, int Y2, DWORD flags)
+ { return m_Data.Viewer((char *)fileName, (char *)title, X1, Y1, X2, Y2, flags); }
+ int Viewer(const char *fileName)
+ { return Viewer(fileName, NULL, 0, 0, -1, -1, VF_NONMODAL); }
+
+};
+
+class CScreenRestorer
+{
+ bool m_Saved;
+ HANDLE m_HANDLE;
+public:
+ CScreenRestorer(): m_Saved(false){};
+ ~CScreenRestorer();
+ void Save();
+ void Restore();
+};
+
+
+extern CStartupInfo g_StartupInfo;
+
+void PrintErrorMessage(const char *message, int code);
+void PrintErrorMessage(const char *message, const char *aText);
+
+#define MY_TRY_BEGIN try\
+ {
+
+#define MY_TRY_END1(x) }\
+ catch(int n) { PrintErrorMessage(x, n); return; }\
+ catch(const CSysString &s) { PrintErrorMessage(x, s); return; }\
+ catch(const char *s) { PrintErrorMessage(x, s); return; }\
+ catch(...) { g_StartupInfo.ShowMessage(x); return; }
+
+#define MY_TRY_END2(x, y) }\
+ catch(int n) { PrintErrorMessage(x, n); return y; }\
+ catch(const CSysString &s) { PrintErrorMessage(x, s); return y; }\
+ catch(const char *s) { PrintErrorMessage(x, s); return y; }\
+ catch(...) { g_StartupInfo.ShowMessage(x); return y; }
+
+bool WasEscPressed();
+void ShowErrorMessage(DWORD errorCode);
+void ShowLastErrorMessage();
+
+}
+
+#endif
diff --git a/CPP/7zip/UI/Far/Main.cpp b/CPP/7zip/UI/Far/Main.cpp
new file mode 100755
index 00000000..a7994b6d
--- /dev/null
+++ b/CPP/7zip/UI/Far/Main.cpp
@@ -0,0 +1,622 @@
+// Test Align for updating !!!!!!!!!!!!!!!!!!
+
+#include "StdAfx.h"
+
+// #include <locale.h>
+#include <initguid.h>
+
+#include "Plugin.h"
+
+#include "Common/Wildcard.h"
+#include "Common/DynamicBuffer.h"
+#include "Common/StringConvert.h"
+#include "Common/Defs.h"
+
+#include "Windows/FileFind.h"
+#include "Windows/FileIO.h"
+#include "Windows/FileDir.h"
+#include "Windows/Defs.h"
+
+#include "../../IPassword.h"
+#include "../../Common/FileStreams.h"
+
+#include "../Common/DefaultName.h"
+#include "../Common/OpenArchive.h"
+#include "../Agent/Agent.h"
+
+#include "ProgressBox.h"
+#include "FarUtils.h"
+#include "Messages.h"
+
+using namespace NWindows;
+using namespace NFar;
+
+static const char *kCommandPrefix = "7-zip";
+
+static const int kDescriptionMaxSize = 256;
+
+static const char *kRegisrtryMainKeyName = "";
+
+static const char *kRegisrtryValueNameEnabled = "UsedByDefault3";
+static bool kPluginEnabledDefault = true;
+
+static const char *kHelpTopicConfig = "Config";
+
+extern "C"
+{
+ void WINAPI SetStartupInfo(struct PluginStartupInfo *info);
+ HANDLE WINAPI OpenFilePlugin(char *name, const unsigned char *Data,
+ unsigned int DataSize);
+ HANDLE WINAPI OpenPlugin(int openFrom, int item);
+ void WINAPI ClosePlugin(HANDLE plugin);
+ int WINAPI GetFindData(HANDLE plugin, struct PluginPanelItem **panelItems,
+ int *itemsNumber, int OpMode);
+ void WINAPI FreeFindData(HANDLE plugin, struct PluginPanelItem *panelItems,
+ int itemsNumber);
+ int WINAPI GetFiles(HANDLE plugin, struct PluginPanelItem *panelItems,
+ int itemsNumber, int move, char *destPath, int opMode);
+ int WINAPI SetDirectory(HANDLE plugin, char *dir, int opMode);
+ void WINAPI GetPluginInfo(struct PluginInfo *info);
+ int WINAPI Configure(int itemNumber);
+ void WINAPI GetOpenPluginInfo(HANDLE plugin, struct OpenPluginInfo *info);
+ int WINAPI PutFiles(HANDLE plugin, struct PluginPanelItem *panelItems,
+ int itemsNumber, int move, int opMode);
+ int WINAPI DeleteFiles(HANDLE plugin, PluginPanelItem *panelItems,
+ int itemsNumber, int opMode);
+ int WINAPI ProcessKey(HANDLE plugin, int key, unsigned int controlState);
+};
+
+HINSTANCE g_hInstance;
+#ifndef _UNICODE
+bool g_IsNT = false;
+static bool IsItWindowsNT()
+{
+ OSVERSIONINFO versionInfo;
+ versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+ if (!::GetVersionEx(&versionInfo))
+ return false;
+ return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+#endif
+
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ g_hInstance = hInstance;
+ #ifndef _UNICODE
+ g_IsNT = IsItWindowsNT();
+ #endif
+ }
+ return TRUE;
+}
+
+static struct COptions
+{
+ bool Enabled;
+} g_Options;
+
+static const char *kPliginNameForRegestry = "7-ZIP";
+
+// #define MY_TRY_BEGIN MY_TRY_BEGIN NCOM::CComInitializer aComInitializer;
+
+void WINAPI SetStartupInfo(struct PluginStartupInfo *info)
+{
+ MY_TRY_BEGIN;
+ g_StartupInfo.Init(*info, kPliginNameForRegestry);
+ g_Options.Enabled = g_StartupInfo.QueryRegKeyValue(
+ HKEY_CURRENT_USER, kRegisrtryMainKeyName,
+ kRegisrtryValueNameEnabled, kPluginEnabledDefault);
+ MY_TRY_END1("SetStartupInfo");
+}
+
+class COpenArchiveCallback:
+ public IArchiveOpenCallback,
+ public IArchiveOpenVolumeCallback,
+ public IProgress,
+ public ICryptoGetTextPassword,
+ public CMyUnknownImp
+{
+ DWORD m_StartTickValue;
+ bool m_MessageBoxIsShown;
+ CMessageBox *m_MessageBox;
+ UINT64 m_NumFiles;
+ UINT64 m_NumFilesMax;
+ UINT64 m_NumFilesPrev;
+ bool m_NumFilesDefined;
+ UINT64 m_NumBytes;
+ bool m_NumBytesDefined;
+ UINT32 m_PrevTickCount;
+
+ NWindows::NFile::NFind::CFileInfoW _fileInfo;
+public:
+ bool PasswordIsDefined;
+ UString Password;
+
+ UString _folderPrefix;
+
+public:
+ MY_UNKNOWN_IMP3(
+ IArchiveOpenVolumeCallback,
+ IProgress,
+ ICryptoGetTextPassword
+ )
+
+ // IProgress
+ STDMETHOD(SetTotal)(UINT64 total);
+ STDMETHOD(SetCompleted)(const UINT64 *aCompleteValue);
+
+ // IArchiveOpenCallback
+ STDMETHOD(SetTotal)(const UINT64 *numFiles, const UINT64 *numBytes);
+ STDMETHOD(SetCompleted)(const UINT64 *numFiles, const UINT64 *numBytes);
+
+ // IArchiveOpenVolumeCallback
+ STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
+ STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
+
+ // ICryptoGetTextPassword
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+
+ void Init(CMessageBox *messageBox)
+ {
+ PasswordIsDefined = false;
+
+ m_NumFilesMax = 0;
+ m_MessageBoxIsShown = false;
+ m_PrevTickCount = GetTickCount();
+ m_MessageBox = messageBox;
+ }
+ void ShowMessage(const UINT64 *completed);
+
+ void LoadFileInfo(const UString &folderPrefix,
+ const UString &fileName)
+ {
+ _folderPrefix = folderPrefix;
+ if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo))
+ throw 1;
+ }
+};
+
+void COpenArchiveCallback::ShowMessage(const UINT64 *completed)
+{
+ UINT32 currentTime = GetTickCount();
+ if (!m_MessageBoxIsShown)
+ {
+ if (currentTime - m_PrevTickCount < 400)
+ return;
+ m_MessageBox->Init(g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
+ g_StartupInfo.GetMsgString(NMessageID::kReading), 2, 30);
+ m_MessageBoxIsShown = true;
+ }
+ else
+ {
+ if (currentTime - m_PrevTickCount < 200)
+ return;
+ }
+ m_PrevTickCount = currentTime;
+ char aMessage[256];
+ sprintf(aMessage, "%5I64u", m_NumFilesMax);
+ char aMessage2[256];
+ aMessage2[0] = '\0';
+ if (completed != NULL)
+ sprintf(aMessage2, "%5I64u", *completed);
+ const char *aMessages[2] =
+ {aMessage, aMessage2 };
+ m_MessageBox->ShowProcessMessages(aMessages);
+}
+
+STDMETHODIMP COpenArchiveCallback::SetTotal(const UINT64 *numFiles, const UINT64 *numBytes)
+{
+ if (WasEscPressed())
+ return E_ABORT;
+ m_NumFilesDefined = (numFiles != NULL);
+ if (m_NumFilesDefined)
+ m_NumFiles = *numFiles;
+ m_NumBytesDefined = (numBytes != NULL);
+ if (m_NumBytesDefined)
+ m_NumBytes = *numBytes;
+ return S_OK;
+}
+
+STDMETHODIMP COpenArchiveCallback::SetCompleted(const UINT64 *numFiles, const UINT64 * /* numBytes */)
+{
+ if (WasEscPressed())
+ return E_ABORT;
+ if (numFiles == NULL)
+ return S_OK;
+ m_NumFilesMax = *numFiles;
+ // if (*numFiles % 100 != 0)
+ // return S_OK;
+ ShowMessage(NULL);
+ return S_OK;
+}
+
+
+STDMETHODIMP COpenArchiveCallback::SetTotal(const UINT64 /* total */)
+{
+ if (WasEscPressed())
+ return E_ABORT;
+ /*
+ aNumFilesDefined = (numFiles != NULL);
+ if (aNumFilesDefined)
+ aNumFiles = *numFiles;
+ aNumBytesDefined = (numBytes != NULL);
+ if (aNumBytesDefined)
+ aNumBytes = *numBytes;
+ */
+ return S_OK;
+}
+
+STDMETHODIMP COpenArchiveCallback::SetCompleted(const UINT64 *completed)
+{
+ if (WasEscPressed())
+ return E_ABORT;
+ if (completed == NULL)
+ return S_OK;
+ // if (*completed % 100 != 0)
+ // return S_OK;
+ ShowMessage(completed);
+ return S_OK;
+}
+
+STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name,
+ IInStream **inStream)
+{
+ if (WasEscPressed())
+ return E_ABORT;
+ *inStream = NULL;
+ UString fullPath = _folderPrefix + name;
+ if (!NWindows::NFile::NFind::FindFile(fullPath, _fileInfo))
+ return S_FALSE;
+ if (_fileInfo.IsDirectory())
+ return S_FALSE;
+ CInFileStream *inFile = new CInFileStream;
+ CMyComPtr<IInStream> inStreamTemp = inFile;
+ if (!inFile->Open(fullPath))
+ return ::GetLastError();
+ *inStream = inStreamTemp.Detach();
+ return S_OK;
+}
+
+
+STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case kpidName:
+ propVariant = GetUnicodeString(_fileInfo.Name, CP_OEMCP);
+ break;
+ case kpidIsFolder:
+ propVariant = _fileInfo.IsDirectory();
+ break;
+ case kpidSize:
+ propVariant = _fileInfo.Size;
+ break;
+ case kpidAttributes:
+ propVariant = (UINT32)_fileInfo.Attributes;
+ break;
+ case kpidLastAccessTime:
+ propVariant = _fileInfo.LastAccessTime;
+ break;
+ case kpidCreationTime:
+ propVariant = _fileInfo.CreationTime;
+ break;
+ case kpidLastWriteTime:
+ propVariant = _fileInfo.LastWriteTime;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
+
+HRESULT GetPassword(UString &password)
+{
+ if (WasEscPressed())
+ return E_ABORT;
+ password.Empty();
+ CInitDialogItem initItems[]=
+ {
+ { DI_DOUBLEBOX, 3, 1, 72, 4, false, false, 0, false, NMessageID::kGetPasswordTitle, NULL, NULL },
+ { DI_TEXT, 5, 2, 0, 0, false, false, DIF_SHOWAMPERSAND, false, NMessageID::kEnterPasswordForFile, NULL, NULL },
+ { DI_PSWEDIT, 5, 3, 70, 3, true, false, 0, true, -1, "", NULL }
+ };
+
+ const int kNumItems = sizeof(initItems)/sizeof(initItems[0]);
+ FarDialogItem dialogItems[kNumItems];
+ g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumItems);
+
+ // sprintf(DialogItems[1].Data,GetMsg(MGetPasswordForFile),FileName);
+ if (g_StartupInfo.ShowDialog(76, 6, NULL, dialogItems, kNumItems) < 0)
+ return (E_ABORT);
+
+ AString oemPassword = dialogItems[2].Data;
+ password = MultiByteToUnicodeString(oemPassword, CP_OEMCP);
+ return S_OK;
+}
+
+STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password)
+{
+ if (!PasswordIsDefined)
+ {
+ RINOK(GetPassword(Password));
+ PasswordIsDefined = true;
+ }
+ CMyComBSTR temp = Password;
+ *password = temp.Detach();
+ return S_OK;
+}
+
+/*
+HRESULT OpenArchive(const CSysString &fileName,
+ IInFolderArchive **archiveHandlerResult,
+ CArchiverInfo &archiverInfoResult,
+ UString &defaultName,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ HRESULT OpenArchive(const CSysString &fileName,
+ #ifndef EXCLUDE_COM
+ HMODULE *module,
+ #endif
+ IInArchive **archive,
+ CArchiverInfo &archiverInfoResult,
+ IArchiveOpenCallback *openArchiveCallback);
+}
+*/
+
+static HANDLE MyOpenFilePlugin(const char *name)
+{
+ UINT codePage = ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ UString normalizedName = GetUnicodeString(name, codePage);
+ normalizedName.Trim();
+ UString fullName;
+ int fileNamePartStartIndex;
+ NFile::NDirectory::MyGetFullPathName(normalizedName, fullName, fileNamePartStartIndex);
+ NFile::NFind::CFileInfoW fileInfo;
+ if (!NFile::NFind::FindFile(fullName, fileInfo))
+ return INVALID_HANDLE_VALUE;
+ if (fileInfo.IsDirectory())
+ return INVALID_HANDLE_VALUE;
+
+
+ CMyComPtr<IInFolderArchive> archiveHandler;
+
+ // CArchiverInfo archiverInfoResult;
+ // ::OutputDebugString("before OpenArchive\n");
+
+ COpenArchiveCallback *openArchiveCallbackSpec = new COpenArchiveCallback;
+
+ CMyComPtr<IArchiveOpenCallback> openArchiveCallback = openArchiveCallbackSpec;
+
+ // if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)
+ CScreenRestorer screenRestorer;
+ CMessageBox m_MessageBox;
+ {
+ screenRestorer.Save();
+ }
+ openArchiveCallbackSpec->Init(&m_MessageBox);
+ openArchiveCallbackSpec->LoadFileInfo(
+ fullName.Left(fileNamePartStartIndex),
+ fullName.Mid(fileNamePartStartIndex));
+
+ // ::OutputDebugString("before OpenArchive\n");
+
+ archiveHandler = new CAgent;
+ CMyComBSTR archiveType;
+ HRESULT result = archiveHandler->Open(
+ GetUnicodeString(fullName, CP_OEMCP), &archiveType, openArchiveCallback);
+ /*
+ HRESULT result = ::OpenArchive(fullName, &archiveHandler,
+ archiverInfoResult, defaultName, openArchiveCallback);
+ */
+ if (result != S_OK)
+ {
+ if (result == E_ABORT)
+ return (HANDLE)-2;
+ return INVALID_HANDLE_VALUE;
+ }
+
+ // ::OutputDebugString("after OpenArchive\n");
+
+ CPlugin *plugin = new CPlugin(
+ fullName,
+ // defaultName,
+ archiveHandler,
+ (const wchar_t *)archiveType
+ );
+ if (plugin == NULL)
+ return(INVALID_HANDLE_VALUE);
+ plugin->PasswordIsDefined = openArchiveCallbackSpec->PasswordIsDefined;
+ plugin->Password = openArchiveCallbackSpec->Password;
+
+ return (HANDLE)(plugin);
+}
+
+HANDLE WINAPI OpenFilePlugin(char *name,
+ const unsigned char * /* data */, unsigned int /* dataSize */)
+{
+ MY_TRY_BEGIN;
+ if (name == NULL || (!g_Options.Enabled))
+ {
+ // if (!Opt.ProcessShiftF1)
+ return(INVALID_HANDLE_VALUE);
+ }
+ return MyOpenFilePlugin(name);
+ MY_TRY_END2("OpenFilePlugin", INVALID_HANDLE_VALUE);
+}
+
+HANDLE WINAPI OpenPlugin(int openFrom, int item)
+{
+ MY_TRY_BEGIN;
+ if(openFrom == OPEN_COMMANDLINE)
+ {
+ CSysString fileName = (const char *)item;
+ if(fileName.IsEmpty())
+ return INVALID_HANDLE_VALUE;
+ if (fileName.Length() >= 2 &&
+ fileName[0] == '\"' && fileName[fileName.Length() - 1] == '\"')
+ fileName = fileName.Mid(1, fileName.Length() - 2);
+
+ return MyOpenFilePlugin(fileName);
+ }
+ if(openFrom == OPEN_PLUGINSMENU)
+ {
+ switch(item)
+ {
+ case 0:
+ {
+ PluginPanelItem pluginPanelItem;
+ if(!g_StartupInfo.ControlGetActivePanelCurrentItemInfo(pluginPanelItem))
+ throw 142134;
+ return MyOpenFilePlugin(pluginPanelItem.FindData.cFileName);
+ }
+ case 1:
+ {
+ CObjectVector<PluginPanelItem> pluginPanelItem;
+ if(!g_StartupInfo.ControlGetActivePanelSelectedOrCurrentItems(pluginPanelItem))
+ throw 142134;
+ if (CompressFiles(pluginPanelItem) == S_OK)
+ {
+ int t = g_StartupInfo.ControlClearPanelSelection();
+ g_StartupInfo.ControlRequestActivePanel(FCTL_UPDATEPANEL, NULL);
+ g_StartupInfo.ControlRequestActivePanel(FCTL_REDRAWPANEL, NULL);
+ g_StartupInfo.ControlRequestActivePanel(FCTL_UPDATEANOTHERPANEL, NULL);
+ g_StartupInfo.ControlRequestActivePanel(FCTL_REDRAWANOTHERPANEL, NULL);
+ }
+ return INVALID_HANDLE_VALUE;
+ }
+ default:
+ throw 4282215;
+ }
+ }
+ return INVALID_HANDLE_VALUE;
+ MY_TRY_END2("OpenPlugin", INVALID_HANDLE_VALUE);
+}
+
+void WINAPI ClosePlugin(HANDLE plugin)
+{
+ MY_TRY_BEGIN;
+ delete (CPlugin *)plugin;
+ MY_TRY_END1("ClosePlugin");
+}
+
+int WINAPI GetFindData(HANDLE plugin, struct PluginPanelItem **panelItems,
+ int *itemsNumber,int opMode)
+{
+ MY_TRY_BEGIN;
+ return(((CPlugin *)plugin)->GetFindData(panelItems, itemsNumber, opMode));
+ MY_TRY_END2("GetFindData", FALSE);
+}
+
+void WINAPI FreeFindData(HANDLE plugin, struct PluginPanelItem *panelItems,
+ int itemsNumber)
+{
+ MY_TRY_BEGIN;
+ ((CPlugin *)plugin)->FreeFindData(panelItems, itemsNumber);
+ MY_TRY_END1("FreeFindData");
+}
+
+int WINAPI GetFiles(HANDLE plugin, struct PluginPanelItem *panelItems,
+ int itemsNumber, int move, char *destPath, int opMode)
+{
+ MY_TRY_BEGIN;
+ return(((CPlugin *)plugin)->GetFiles(panelItems, itemsNumber, move, destPath, opMode));
+ MY_TRY_END2("GetFiles", NFileOperationReturnCode::kError);
+}
+
+int WINAPI SetDirectory(HANDLE plugin, char *dir, int opMode)
+{
+ MY_TRY_BEGIN;
+ return(((CPlugin *)plugin)->SetDirectory(dir, opMode));
+ MY_TRY_END2("SetDirectory", FALSE);
+}
+
+void WINAPI GetPluginInfo(struct PluginInfo *info)
+{
+ MY_TRY_BEGIN;
+
+ info->StructSize = sizeof(*info);
+ info->Flags = 0;
+ info->DiskMenuStrings = NULL;
+ info->DiskMenuNumbers = NULL;
+ info->DiskMenuStringsNumber = 0;
+ static const char *pluginMenuStrings[2];
+ pluginMenuStrings[0] = g_StartupInfo.GetMsgString(NMessageID::kOpenArchiveMenuString);
+ pluginMenuStrings[1] = g_StartupInfo.GetMsgString(NMessageID::kCreateArchiveMenuString);
+ info->PluginMenuStrings = (char **)pluginMenuStrings;
+ info->PluginMenuStringsNumber = 2;
+ static const char *pluginCfgStrings[1];
+ pluginCfgStrings[0] = g_StartupInfo.GetMsgString(NMessageID::kOpenArchiveMenuString);
+ info->PluginConfigStrings = (char **)pluginCfgStrings;
+ info->PluginConfigStringsNumber = sizeof(pluginCfgStrings) / sizeof(pluginCfgStrings[0]);
+ info->CommandPrefix = (char *)kCommandPrefix;
+ MY_TRY_END1("GetPluginInfo");
+}
+
+int WINAPI Configure(int itemNumber)
+{
+ MY_TRY_BEGIN;
+
+ const int kEnabledCheckBoxIndex = 1;
+
+ const int kYSize = 7;
+
+ struct CInitDialogItem initItems[]=
+ {
+ { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kConfigTitle, NULL, NULL },
+ { DI_CHECKBOX, 5, 2, 0, 0, true, g_Options.Enabled, 0, false, NMessageID::kConfigPluginEnabled, NULL, NULL },
+ { DI_TEXT, 5, 3, 0, 0, false, false, DIF_BOXCOLOR | DIF_SEPARATOR, false, -1, "", NULL },
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kOk, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL },
+ };
+
+ const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);
+ const int kOkButtonIndex = kNumDialogItems - 2;
+
+ FarDialogItem dialogItems[kNumDialogItems];
+ g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
+
+ int askCode = g_StartupInfo.ShowDialog(76, kYSize,
+ kHelpTopicConfig, dialogItems, kNumDialogItems);
+
+ if (askCode != kOkButtonIndex)
+ return (FALSE);
+
+ g_Options.Enabled = BOOLToBool(dialogItems[kEnabledCheckBoxIndex].Selected);
+
+ g_StartupInfo.SetRegKeyValue(HKEY_CURRENT_USER, kRegisrtryMainKeyName,
+ kRegisrtryValueNameEnabled, g_Options.Enabled);
+ return(TRUE);
+ MY_TRY_END2("Configure", FALSE);
+}
+
+void WINAPI GetOpenPluginInfo(HANDLE plugin,struct OpenPluginInfo *info)
+{
+ MY_TRY_BEGIN;
+ ((CPlugin *)plugin)->GetOpenPluginInfo(info);
+ MY_TRY_END1("GetOpenPluginInfo");
+}
+
+int WINAPI PutFiles(HANDLE plugin, struct PluginPanelItem *panelItems,
+ int itemsNumber, int move, int opMode)
+{
+ MY_TRY_BEGIN;
+ return(((CPlugin *)plugin)->PutFiles(panelItems, itemsNumber, move, opMode));
+ MY_TRY_END2("PutFiles", NFileOperationReturnCode::kError);
+}
+
+int WINAPI DeleteFiles(HANDLE plugin, PluginPanelItem *panelItems,
+ int itemsNumber, int opMode)
+{
+ MY_TRY_BEGIN;
+ return(((CPlugin *)plugin)->DeleteFiles(panelItems, itemsNumber, opMode));
+ MY_TRY_END2("DeleteFiles", FALSE);
+}
+
+int WINAPI ProcessKey(HANDLE plugin, int key, unsigned int controlState)
+{
+ MY_TRY_BEGIN;
+ return (((CPlugin *)plugin)->ProcessKey(key, controlState));
+ MY_TRY_END2("ProcessKey", FALSE);
+}
diff --git a/CPP/7zip/UI/Far/Messages.h b/CPP/7zip/UI/Far/Messages.h
new file mode 100755
index 00000000..8b6e2a49
--- /dev/null
+++ b/CPP/7zip/UI/Far/Messages.h
@@ -0,0 +1,152 @@
+// SevenZip/ Messages.h
+
+#ifndef __SEVENZIP_MESSAGES_H
+#define __SEVENZIP_MESSAGES_H
+
+namespace NMessageID {
+
+enum EEnum
+{
+ kOk,
+ kCancel,
+
+ kWarning,
+ kError,
+
+ kArchiveType,
+
+ kProperties,
+
+ kYes,
+ kNo,
+
+ kName,
+ kExtension,
+ kIsFolder,
+ kSize,
+ kPackedSize,
+ kAttributes,
+ kCreationTime,
+ kLastAccessTime,
+ kLastWriteTime,
+ kSolid,
+ kCommented,
+ kEncrypted,
+ kSplitBefore,
+ kSplitAfter,
+ kDictionarySize,
+ kCRC,
+ kType,
+ kAnti,
+ kMethod,
+ kHostOS,
+ kFileSystem,
+ kUser,
+ kGroup,
+ kBlock,
+ kComment,
+ kPosition,
+
+ kGetPasswordTitle,
+ kEnterPasswordForFile,
+
+ kExtractTitle,
+ kExtractTo,
+
+ kExtractPathMode,
+ kExtractPathFull,
+ kExtractPathCurrent,
+ kExtractPathNo,
+
+ kExtractOwerwriteMode,
+ kExtractOwerwriteAsk,
+ kExtractOwerwritePrompt,
+ kExtractOwerwriteSkip,
+ kExtractOwerwriteAutoRename,
+ kExtractOwerwriteAutoRenameExisting,
+
+ kExtractFilesMode,
+ kExtractFilesSelected,
+ kExtractFilesAll,
+
+ kExtractPassword,
+
+ kExtractExtract,
+ kExtractCancel,
+
+ kExtractCanNotOpenOutputFile,
+
+ kExtractUnsupportedMethod,
+ kExtractCRCFailed,
+ kExtractDataError,
+
+ kOverwriteTitle,
+ kOverwriteMessage1,
+ kOverwriteMessageWouldYouLike,
+ kOverwriteMessageWithtTisOne,
+
+ kOverwriteBytes,
+ kOverwriteModifiedOn,
+
+ kOverwriteYes,
+ kOverwriteYesToAll,
+ kOverwriteNo,
+ kOverwriteNoToAll,
+ kOverwriteAutoRename,
+ kOverwriteCancel,
+
+ kUpdateNotSupportedForThisArchive,
+
+ kDeleteTitle,
+ kDeleteFile,
+ kDeleteFiles,
+ kDeleteNumberOfFiles,
+ kDeleteDelete,
+ kDeleteCancel,
+
+ kUpdateTitle,
+ kUpdateAddToArchive,
+
+ kUpdateMethod,
+ kUpdateMethodStore,
+ kUpdateMethodFastest,
+ kUpdateMethodFast,
+ kUpdateMethodNormal,
+ kUpdateMethodMaximum,
+ kUpdateMethodUltra,
+
+ kUpdateMode,
+ kUpdateModeAdd,
+ kUpdateModeUpdate,
+ kUpdateModeFreshen,
+ kUpdateModeSynchronize,
+
+ kUpdateAdd,
+ kUpdateSelectArchiver,
+
+ kUpdateSelectArchiverMenuTitle,
+
+ // kArcReadFiles,
+
+ kWaitTitle,
+
+ kReading,
+ kExtracting,
+ kDeleting,
+ kUpdating,
+
+ // kReadingList,
+
+ kMoveIsNotSupported,
+
+ kOpenArchiveMenuString,
+ kCreateArchiveMenuString,
+
+ kConfigTitle,
+
+ kConfigPluginEnabled
+};
+
+}
+
+#endif \ No newline at end of file
diff --git a/CPP/7zip/UI/Far/OverwriteDialog.cpp b/CPP/7zip/UI/Far/OverwriteDialog.cpp
new file mode 100755
index 00000000..028fff4e
--- /dev/null
+++ b/CPP/7zip/UI/Far/OverwriteDialog.cpp
@@ -0,0 +1,109 @@
+// OverwriteDialog.cpp
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#include "OverwriteDialog.h"
+
+#include "Common/String.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/FileName.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariantConversions.h"
+
+#include "FarUtils.h"
+#include "Messages.h"
+
+using namespace NWindows;
+using namespace NFar;
+
+namespace NOverwriteDialog {
+
+static const char *kHelpTopic = "OverwriteDialog";
+
+struct CFileInfoStrings
+{
+ CSysString Size;
+ CSysString Time;
+};
+
+void SetFileInfoStrings(const CFileInfo &fileInfo,
+ CFileInfoStrings &fileInfoStrings)
+{
+ char buffer[256];
+
+ if (fileInfo.SizeIsDefined)
+ {
+ sprintf(buffer, "%I64u ", fileInfo.Size);
+ fileInfoStrings.Size = buffer;
+ fileInfoStrings.Size += g_StartupInfo.GetMsgString(NMessageID::kOverwriteBytes);
+ }
+ else
+ {
+ fileInfoStrings.Size = "";
+ }
+
+ FILETIME localFileTime;
+ if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))
+ throw 4190402;
+ UString timeString = ConvertFileTimeToString(localFileTime);
+
+ fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn);
+ fileInfoStrings.Time += " ";
+ fileInfoStrings.Time += GetSystemString(timeString, CP_OEMCP);
+}
+
+NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInfo)
+{
+ const int kYSize = 20;
+ const int kXSize = 76;
+
+ CFileInfoStrings oldFileInfoStrings;
+ CFileInfoStrings newFileInfoStrings;
+
+ SetFileInfoStrings(oldFileInfo, oldFileInfoStrings);
+ SetFileInfoStrings(newFileInfo, newFileInfoStrings);
+
+ struct CInitDialogItem anInitItems[]={
+ { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kOverwriteTitle, NULL, NULL },
+ { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessage1, NULL, NULL },
+
+ { DI_TEXT, 3, 3, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL },
+
+ { DI_TEXT, 5, 4, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWouldYouLike, NULL, NULL },
+
+ { DI_TEXT, 7, 6, 0, 0, false, false, 0, false, -1, oldFileInfo.Name, NULL },
+ { DI_TEXT, 7, 7, 0, 0, false, false, 0, false, -1, oldFileInfoStrings.Size, NULL },
+ { DI_TEXT, 7, 8, 0, 0, false, false, 0, false, -1, oldFileInfoStrings.Time, NULL },
+
+ { DI_TEXT, 5, 10, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWithtTisOne, NULL, NULL },
+
+ { DI_TEXT, 7, 12, 0, 0, false, false, 0, false, -1, newFileInfo.Name, NULL },
+ { DI_TEXT, 7, 13, 0, 0, false, false, 0, false, -1, newFileInfoStrings.Size, NULL },
+ { DI_TEXT, 7, 14, 0, 0, false, false, 0, false, -1, newFileInfoStrings.Time, NULL },
+
+ { DI_TEXT, 3, kYSize - 5, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL },
+
+ { DI_BUTTON, 0, kYSize - 4, 0, 0, true, false, DIF_CENTERGROUP, true, NMessageID::kOverwriteYes, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteYesToAll, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteNo, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteNoToAll, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteAutoRename, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteCancel, NULL, NULL }
+ };
+
+ const int kNumDialogItems = sizeof(anInitItems) / sizeof(anInitItems[0]);
+ FarDialogItem aDialogItems[kNumDialogItems];
+ g_StartupInfo.InitDialogItems(anInitItems, aDialogItems, kNumDialogItems);
+ int anAskCode = g_StartupInfo.ShowDialog(kXSize, kYSize,
+ NULL, aDialogItems, kNumDialogItems);
+ const int kButtonStartPos = kNumDialogItems - 6;
+ if (anAskCode >= kButtonStartPos && anAskCode < kNumDialogItems)
+ return NResult::EEnum(anAskCode - kButtonStartPos);
+ return NResult::kCancel;
+}
+
+}
+
diff --git a/CPP/7zip/UI/Far/OverwriteDialog.h b/CPP/7zip/UI/Far/OverwriteDialog.h
new file mode 100755
index 00000000..ff1a480e
--- /dev/null
+++ b/CPP/7zip/UI/Far/OverwriteDialog.h
@@ -0,0 +1,33 @@
+// OverwriteDialog.h
+
+#ifndef OVERWRITEDIALOG_H
+#define OVERWRITEDIALOG_H
+
+#include "Common/String.h"
+
+namespace NOverwriteDialog {
+
+struct CFileInfo
+{
+ bool SizeIsDefined;
+ UINT64 Size;
+ FILETIME Time;
+ CSysString Name;
+};
+namespace NResult
+{
+ enum EEnum
+ {
+ kYes,
+ kYesToAll,
+ kNo,
+ kNoToAll,
+ kAutoRename,
+ kCancel,
+ };
+}
+NResult::EEnum Execute(const CFileInfo &anOldFileInfo, const CFileInfo &aNewFileInfo);
+
+}
+
+#endif
diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp
new file mode 100755
index 00000000..0d4b150e
--- /dev/null
+++ b/CPP/7zip/UI/Far/Plugin.cpp
@@ -0,0 +1,693 @@
+// Plugin.cpp
+
+#include "StdAfx.h"
+
+#include "Plugin.h"
+
+#include "Common/StringConvert.h"
+#include "Common/Wildcard.h"
+
+#include "Windows/PropVariantConversions.h"
+#include "Windows/FileName.h"
+#include "Windows/FileDir.h"
+
+#include "../Common/PropIDUtils.h"
+
+#include "Messages.h"
+#include "FarUtils.h"
+
+using namespace NWindows;
+using namespace NFar;
+
+CSysString ConvertPropertyToString2(const PROPVARIANT &propVariant, PROPID propID)
+{
+ if (propVariant.vt == VT_BSTR)
+ return GetSystemString(propVariant.bstrVal, CP_OEMCP);
+ if (propVariant.vt != VT_BOOL)
+ return GetSystemString(ConvertPropertyToString(propVariant, propID), CP_OEMCP);
+ int messageID = VARIANT_BOOLToBool(propVariant.boolVal) ?
+ NMessageID::kYes : NMessageID::kNo;
+ return g_StartupInfo.GetMsgString(messageID);
+}
+
+CPlugin::CPlugin(const UString &fileName,
+ // const UString &defaultName,
+ IInFolderArchive *archiveHandler,
+ UString archiveTypeName
+ ):
+ m_ArchiveHandler(archiveHandler),
+ m_FileName(fileName),
+ _archiveTypeName(archiveTypeName)
+ // , m_DefaultName(defaultName)
+ // , m_ArchiverInfo(archiverInfo)
+{
+ if (!NFile::NFind::FindFile(m_FileName, m_FileInfo))
+ throw "error";
+ archiveHandler->BindToRootFolder(&_folder);
+}
+
+CPlugin::~CPlugin()
+{
+}
+
+static void MyGetFileTime(IFolderFolder *anArchiveFolder, UINT32 itemIndex,
+ PROPID propID, FILETIME &fileTime)
+{
+ NCOM::CPropVariant propVariant;
+ if (anArchiveFolder->GetProperty(itemIndex, propID, &propVariant) != S_OK)
+ throw 271932;
+ if (propVariant.vt == VT_EMPTY)
+ {
+ fileTime.dwHighDateTime = 0;
+ fileTime.dwLowDateTime = 0;
+ }
+ else
+ {
+ if (propVariant.vt != VT_FILETIME)
+ throw 4191730;
+ fileTime = propVariant.filetime;
+ }
+}
+
+void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UINT32 itemIndex)
+{
+ NCOM::CPropVariant propVariant;
+ if (_folder->GetProperty(itemIndex, kpidName, &propVariant) != S_OK)
+ throw 271932;
+
+ if (propVariant.vt != VT_BSTR)
+ throw 272340;
+
+ CSysString oemString = UnicodeStringToMultiByte(propVariant.bstrVal, CP_OEMCP);
+ strcpy(panelItem.FindData.cFileName, oemString);
+ panelItem.FindData.cAlternateFileName[0] = 0;
+
+ if (_folder->GetProperty(itemIndex, kpidAttributes, &propVariant) != S_OK)
+ throw 271932;
+ if (propVariant.vt == VT_UI4)
+ panelItem.FindData.dwFileAttributes = propVariant.ulVal;
+ else if (propVariant.vt == VT_EMPTY)
+ panelItem.FindData.dwFileAttributes = m_FileInfo.Attributes;
+ else
+ throw 21631;
+
+ if (_folder->GetProperty(itemIndex, kpidIsFolder, &propVariant) != S_OK)
+ throw 271932;
+ if (propVariant.vt == VT_BOOL)
+ {
+ if (VARIANT_BOOLToBool(propVariant.boolVal))
+ panelItem.FindData.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+ }
+ else if (propVariant.vt != VT_EMPTY)
+ throw 21632;
+
+ if (_folder->GetProperty(itemIndex, kpidSize, &propVariant) != S_OK)
+ throw 271932;
+ UINT64 length;
+ if (propVariant.vt == VT_EMPTY)
+ length = 0;
+ else
+ length = ::ConvertPropVariantToUInt64(propVariant);
+ panelItem.FindData.nFileSizeLow = UINT32(length);
+ panelItem.FindData.nFileSizeHigh = UINT32(length >> 32);
+
+ MyGetFileTime(_folder, itemIndex, kpidCreationTime, panelItem.FindData.ftCreationTime);
+ MyGetFileTime(_folder, itemIndex, kpidLastAccessTime, panelItem.FindData.ftLastAccessTime);
+ MyGetFileTime(_folder, itemIndex, kpidLastWriteTime, panelItem.FindData.ftLastWriteTime);
+
+ if (panelItem.FindData.ftLastWriteTime.dwHighDateTime == 0 &&
+ panelItem.FindData.ftLastWriteTime.dwLowDateTime == 0)
+ panelItem.FindData.ftLastWriteTime = m_FileInfo.LastWriteTime;
+
+ if (_folder->GetProperty(itemIndex, kpidPackedSize, &propVariant) != S_OK)
+ throw 271932;
+ if (propVariant.vt == VT_EMPTY)
+ length = 0;
+ else
+ length = ::ConvertPropVariantToUInt64(propVariant);
+ panelItem.PackSize = UINT32(length);
+ panelItem.PackSizeHigh = UINT32(length >> 32);
+
+ panelItem.Flags = 0;
+ panelItem.NumberOfLinks = 0;
+
+ panelItem.Description = NULL;
+ panelItem.Owner = NULL;
+ panelItem.CustomColumnData = NULL;
+ panelItem.CustomColumnNumber = 0;
+
+ panelItem.Reserved[0] = 0;
+ panelItem.Reserved[1] = 0;
+ panelItem.Reserved[2] = 0;
+
+
+}
+
+int CPlugin::GetFindData(PluginPanelItem **panelItems,
+ int *itemsNumber, int opMode)
+{
+ // CScreenRestorer screenRestorer;
+ if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)
+ {
+ /*
+ screenRestorer.Save();
+ const char *aMsgItems[]=
+ {
+ g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
+ g_StartupInfo.GetMsgString(NMessageID::kReadingList)
+ };
+ g_StartupInfo.ShowMessage(0, NULL, aMsgItems,
+ sizeof(aMsgItems) / sizeof(aMsgItems[0]), 0);
+ */
+ }
+
+ UINT32 numItems;
+ _folder->GetNumberOfItems(&numItems);
+ *panelItems = new PluginPanelItem[numItems];
+ try
+ {
+ for(UINT32 i = 0; i < numItems; i++)
+ {
+ PluginPanelItem &panelItem = (*panelItems)[i];
+ ReadPluginPanelItem(panelItem, i);
+ panelItem.UserData = i;
+ }
+ }
+ catch(...)
+ {
+ delete [](*panelItems);
+ throw;
+ }
+ *itemsNumber = numItems;
+ return(TRUE);
+}
+
+void CPlugin::FreeFindData(struct PluginPanelItem *panelItems,
+ int itemsNumber)
+{
+ for(int i = 0; i < itemsNumber; i++)
+ if(panelItems[i].Description != NULL)
+ delete []panelItems[i].Description;
+ delete []panelItems;
+}
+
+
+void CPlugin::EnterToDirectory(const UString &aDirName)
+{
+ CMyComPtr<IFolderFolder> newFolder;
+ _folder->BindToFolder(aDirName, &newFolder);
+ if(newFolder == NULL)
+ if (aDirName.IsEmpty())
+ return;
+ else
+ throw 40325;
+ _folder = newFolder;
+}
+
+int CPlugin::SetDirectory(const char *aszDir, int opMode)
+{
+ UString path = MultiByteToUnicodeString(aszDir, CP_OEMCP);
+ if (path == L"\\")
+ {
+ _folder.Release();
+ m_ArchiveHandler->BindToRootFolder(&_folder);
+ }
+ else if (path == L"..")
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ _folder->BindToParentFolder(&newFolder);
+ if (newFolder == NULL)
+ throw 40312;
+ _folder = newFolder;
+ }
+ else if (path.IsEmpty())
+ EnterToDirectory(path);
+ else
+ {
+ if (path[0] == L'\\')
+ {
+ _folder.Release();
+ m_ArchiveHandler->BindToRootFolder(&_folder);
+ path = path.Mid(1);
+ }
+ UStringVector pathParts;
+ SplitPathToParts(path, pathParts);
+ for(int i = 0; i < pathParts.Size(); i++)
+ EnterToDirectory(pathParts[i]);
+ }
+ GetCurrentDir();
+ return TRUE;
+}
+
+void CPlugin::GetPathParts(UStringVector &pathParts)
+{
+ pathParts.Clear();
+ CMyComPtr<IFolderFolder> folderItem = _folder;
+ for (;;)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ folderItem->BindToParentFolder(&newFolder);
+ if (newFolder == NULL)
+ break;
+ CMyComBSTR name;
+ folderItem->GetName(&name);
+ pathParts.Insert(0, (const wchar_t *)name);
+ folderItem = newFolder;
+ }
+}
+
+void CPlugin::GetCurrentDir()
+{
+ m_CurrentDir.Empty();
+ UStringVector pathParts;
+ GetPathParts(pathParts);
+ for (int i = 0; i < pathParts.Size(); i++)
+ {
+ m_CurrentDir += L'\\';
+ m_CurrentDir += pathParts[i];
+ }
+}
+
+static char *kPluginFormatName = "7-ZIP";
+
+
+struct CPROPIDToName
+{
+ PROPID PropID;
+ int PluginID;
+};
+
+static CPROPIDToName kPROPIDToName[] =
+{
+ { kpidName, NMessageID::kName },
+ { kpidExtension, NMessageID::kExtension },
+ { kpidIsFolder, NMessageID::kIsFolder },
+ { kpidSize, NMessageID::kSize },
+ { kpidPackedSize, NMessageID::kPackedSize },
+ { kpidAttributes, NMessageID::kAttributes },
+ { kpidCreationTime, NMessageID::kCreationTime },
+ { kpidLastAccessTime, NMessageID::kLastAccessTime },
+ { kpidLastWriteTime, NMessageID::kLastWriteTime },
+ { kpidSolid, NMessageID::kSolid },
+ { kpidCommented, NMessageID::kCommented },
+ { kpidEncrypted, NMessageID::kEncrypted },
+ { kpidSplitBefore, NMessageID::kSplitBefore },
+ { kpidSplitAfter, NMessageID::kSplitAfter },
+ { kpidDictionarySize, NMessageID::kDictionarySize },
+ { kpidCRC, NMessageID::kCRC },
+ { kpidType, NMessageID::kType },
+ { kpidIsAnti, NMessageID::kAnti },
+ { kpidMethod, NMessageID::kMethod },
+ { kpidHostOS, NMessageID::kHostOS },
+ { kpidFileSystem, NMessageID::kFileSystem },
+ { kpidUser, NMessageID::kUser },
+ { kpidGroup, NMessageID::kGroup },
+ { kpidBlock, NMessageID::kBlock },
+ { kpidComment, NMessageID::kComment },
+ { kpidPosition, NMessageID::kPosition }
+
+};
+
+static const int kNumPROPIDToName = sizeof(kPROPIDToName) / sizeof(kPROPIDToName[0]);
+
+static int FindPropertyToName(PROPID propID)
+{
+ for(int i = 0; i < kNumPROPIDToName; i++)
+ if(kPROPIDToName[i].PropID == propID)
+ return i;
+ return -1;
+}
+
+/*
+struct CPropertyIDInfo
+{
+ PROPID PropID;
+ const char *FarID;
+ int Width;
+ // char CharID;
+};
+
+static CPropertyIDInfo kPropertyIDInfos[] =
+{
+ { kpidName, "N", 0},
+ { kpidSize, "S", 8},
+ { kpidPackedSize, "P", 8},
+ { kpidAttributes, "A", 0},
+ { kpidCreationTime, "DC", 14},
+ { kpidLastAccessTime, "DA", 14},
+ { kpidLastWriteTime, "DM", 14},
+
+ { kpidSolid, NULL, 0, 'S'},
+ { kpidEncrypted, NULL, 0, 'P'}
+
+ { kpidDictionarySize, IDS_PROPERTY_DICTIONARY_SIZE },
+ { kpidSplitBefore, NULL, 'B'},
+ { kpidSplitAfter, NULL, 'A'},
+ { kpidComment, , NULL, 'C'},
+ { kpidCRC, IDS_PROPERTY_CRC }
+ // { kpidType, L"Type" }
+};
+
+static const int kNumPropertyIDInfos = sizeof(kPropertyIDInfos) /
+ sizeof(kPropertyIDInfos[0]);
+
+static int FindPropertyInfo(PROPID propID)
+{
+ for(int i = 0; i < kNumPropertyIDInfos; i++)
+ if(kPropertyIDInfos[i].PropID == propID)
+ return i;
+ return -1;
+}
+*/
+
+// char *g_Titles[] = { "a", "f", "v" };
+static void SmartAddToString(AString &aDestString, const char *aSrcString)
+{
+ if (!aDestString.IsEmpty())
+ aDestString += ',';
+ aDestString += aSrcString;
+}
+
+/*
+void CPlugin::AddColumn(PROPID propID)
+{
+ int index = FindPropertyInfo(propID);
+ if (index >= 0)
+ {
+ for(int i = 0; i < m_ProxyHandler->m_InternalProperties.Size(); i++)
+ {
+ const CArchiveItemProperty &aHandlerProperty = m_ProxyHandler->m_InternalProperties[i];
+ if (aHandlerProperty.ID == propID)
+ break;
+ }
+ if (i == m_ProxyHandler->m_InternalProperties.Size())
+ return;
+
+ const CPropertyIDInfo &aPropertyIDInfo = kPropertyIDInfos[index];
+ SmartAddToString(PanelModeColumnTypes, aPropertyIDInfo.FarID);
+ char aTmp[32];
+ itoa(aPropertyIDInfo.Width, aTmp, 10);
+ SmartAddToString(PanelModeColumnWidths, aTmp);
+ return;
+ }
+}
+*/
+
+void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info)
+{
+ info->StructSize = sizeof(*info);
+ info->Flags = OPIF_USEFILTER | OPIF_USESORTGROUPS| OPIF_USEHIGHLIGHTING|
+ OPIF_ADDDOTS | OPIF_COMPAREFATTIME;
+
+ UINT codePage = ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ strcpy(m_FileNameBuffer, UnicodeStringToMultiByte(m_FileName, codePage));
+ info->HostFile = m_FileNameBuffer; // test it it is not static
+
+ strcpy(m_CurrentDirBuffer, UnicodeStringToMultiByte(m_CurrentDir, CP_OEMCP));
+ info->CurDir = m_CurrentDirBuffer;
+
+ info->Format = kPluginFormatName;
+
+ UString name;
+ {
+ UString fullName;
+ int index;
+ NFile::NDirectory::MyGetFullPathName(m_FileName, fullName, index);
+ name = fullName.Mid(index);
+ }
+
+ m_PannelTitle =
+ UString(L' ') +
+ _archiveTypeName +
+ UString(L':') +
+ name +
+ UString(L' ');
+ if(!m_CurrentDir.IsEmpty())
+ {
+ // m_PannelTitle += '\\';
+ m_PannelTitle += m_CurrentDir;
+ }
+
+ strcpy(m_PannelTitleBuffer, UnicodeStringToMultiByte(m_PannelTitle, CP_OEMCP));
+ info->PanelTitle = m_PannelTitleBuffer;
+
+ memset(m_InfoLines,0,sizeof(m_InfoLines));
+ strcpy(m_InfoLines[0].Text,"");
+ m_InfoLines[0].Separator = TRUE;
+
+ strcpy(m_InfoLines[1].Text, g_StartupInfo.GetMsgString(NMessageID::kArchiveType));
+ strcpy(m_InfoLines[1].Data, UnicodeStringToMultiByte(_archiveTypeName, CP_OEMCP));
+
+ int numItems = 2;
+ UINT32 numProps;
+ if (m_ArchiveHandler->GetNumberOfArchiveProperties(&numProps) == S_OK)
+ {
+ for (UINT32 i = 0; i < numProps && numItems < 30; i++)
+ {
+ CMyComBSTR name;
+ PROPID propID;
+ VARTYPE vt;
+ if (m_ArchiveHandler->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK)
+ continue;
+
+ InfoPanelLine &item = m_InfoLines[numItems];
+ int index = FindPropertyToName(propID);
+ if (index < 0)
+ {
+ if (name != 0)
+ strcpy(item.Text, UnicodeStringToMultiByte(
+ (const wchar_t *)name, CP_OEMCP));
+ else
+ strcpy(item.Text, "");
+ }
+ else
+ strcpy(item.Text, g_StartupInfo.GetMsgString(kPROPIDToName[index].PluginID));
+
+ NCOM::CPropVariant propVariant;
+ if (m_ArchiveHandler->GetArchiveProperty(propID, &propVariant) != S_OK)
+ continue;
+ CSysString s = ConvertPropertyToString2(propVariant, propID);
+ strcpy(item.Data, s);
+ numItems++;
+ }
+ }
+
+ //m_InfoLines[1].Separator = 0;
+
+ info->InfoLines = m_InfoLines;
+ info->InfoLinesNumber = numItems;
+
+
+ info->DescrFiles = NULL;
+ info->DescrFilesNumber = 0;
+
+ PanelModeColumnTypes.Empty();
+ PanelModeColumnWidths.Empty();
+
+ /*
+ AddColumn(kpidName);
+ AddColumn(kpidSize);
+ AddColumn(kpidPackedSize);
+ AddColumn(kpidLastWriteTime);
+ AddColumn(kpidCreationTime);
+ AddColumn(kpidLastAccessTime);
+ AddColumn(kpidAttributes);
+
+ PanelMode.ColumnTypes = (char *)(const char *)PanelModeColumnTypes;
+ PanelMode.ColumnWidths = (char *)(const char *)PanelModeColumnWidths;
+ PanelMode.ColumnTitles = NULL;
+ PanelMode.FullScreen = TRUE;
+ PanelMode.DetailedStatus = FALSE;
+ PanelMode.AlignExtensions = FALSE;
+ PanelMode.CaseConversion = FALSE;
+ PanelMode.StatusColumnTypes = "N";
+ PanelMode.StatusColumnWidths = "0";
+ PanelMode.Reserved[0] = 0;
+ PanelMode.Reserved[1] = 0;
+
+ info->PanelModesArray = &PanelMode;
+ info->PanelModesNumber = 1;
+ */
+
+ info->PanelModesArray = NULL;
+ info->PanelModesNumber = 0;
+
+ info->StartPanelMode = 0;
+ info->StartSortMode = 0;
+ info->KeyBar = NULL;
+ info->ShortcutData = NULL;
+}
+
+struct CArchiveItemProperty
+{
+ AString Name;
+ PROPID ID;
+ VARTYPE Type;
+};
+
+HRESULT CPlugin::ShowAttributesWindow()
+{
+ PluginPanelItem pluginPanelItem;
+ if (!g_StartupInfo.ControlGetActivePanelCurrentItemInfo(pluginPanelItem))
+ return S_FALSE;
+ if (strcmp(pluginPanelItem.FindData.cFileName, "..") == 0 &&
+ NFile::NFind::NAttributes::IsDirectory(pluginPanelItem.FindData.dwFileAttributes))
+ return S_FALSE;
+ int itemIndex = pluginPanelItem.UserData;
+
+ CObjectVector<CArchiveItemProperty> properties;
+ UINT32 numProps;
+ RINOK(m_ArchiveHandler->GetNumberOfProperties(&numProps));
+ int i;
+ for (i = 0; i < (int)numProps; i++)
+ {
+ CMyComBSTR name;
+ PROPID propID;
+ VARTYPE vt;
+ RINOK(m_ArchiveHandler->GetPropertyInfo(i, &name, &propID, &vt));
+ CArchiveItemProperty destProperty;
+ destProperty.Type = vt;
+ destProperty.ID = propID;
+ if (destProperty.ID == kpidPath)
+ destProperty.ID = kpidName;
+ AString propName;
+ {
+ if (name != NULL)
+ destProperty.Name = UnicodeStringToMultiByte(
+ (const wchar_t *)name, CP_OEMCP);
+ else
+ destProperty.Name = "Error";
+ }
+ properties.Add(destProperty);
+ }
+
+ /*
+ LPCITEMIDLIST aProperties;
+ if (index < m_FolderItem->m_DirSubItems.Size())
+ {
+ const CArchiveFolderItem &anItem = m_FolderItem->m_DirSubItems[index];
+ aProperties = anItem.m_Properties;
+ }
+ else
+ {
+ const CArchiveFolderFileItem &anItem =
+ m_FolderItem->m_FileSubItems[index - m_FolderItem->m_DirSubItems.Size()];
+ aProperties = anItem.m_Properties;
+ }
+ */
+
+ const int kPathIndex = 2;
+ const int kOkButtonIndex = 4;
+ int size = 2;
+ CRecordVector<CInitDialogItem> initDialogItems;
+
+ int xSize = 70;
+ CInitDialogItem initDialogItem =
+ { DI_DOUBLEBOX, 3, 1, xSize - 4, size - 2, false, false, 0, false, NMessageID::kProperties, NULL, NULL };
+ initDialogItems.Add(initDialogItem);
+ AStringVector aValues;
+
+ for (i = 0; i < properties.Size(); i++)
+ {
+ const CArchiveItemProperty &property = properties[i];
+
+ CInitDialogItem initDialogItem =
+ { DI_TEXT, 5, 3 + i, 0, 0, false, false, 0, false, 0, NULL, NULL };
+ int index = FindPropertyToName(property.ID);
+ if (index < 0)
+ {
+ initDialogItem.DataMessageId = -1;
+ initDialogItem.DataString = property.Name;
+ }
+ else
+ initDialogItem.DataMessageId = kPROPIDToName[index].PluginID;
+ initDialogItems.Add(initDialogItem);
+
+ NCOM::CPropVariant propVariant;
+ RINOK(_folder->GetProperty(itemIndex,
+ property.ID, &propVariant));
+ CSysString aString = ConvertPropertyToString2(propVariant, property.ID);
+ aValues.Add(aString);
+
+ {
+ CInitDialogItem initDialogItem =
+ { DI_TEXT, 30, 3 + i, 0, 0, false, false, 0, false, -1, NULL, NULL };
+ initDialogItems.Add(initDialogItem);
+ }
+ }
+
+ int numLines = aValues.Size();
+ for(i = 0; i < numLines; i++)
+ {
+ CInitDialogItem &initDialogItem = initDialogItems[1 + i * 2 + 1];
+ initDialogItem.DataString = aValues[i];
+ }
+
+ int numDialogItems = initDialogItems.Size();
+
+ CRecordVector<FarDialogItem> dialogItems;
+ dialogItems.Reserve(numDialogItems);
+ for(i = 0; i < numDialogItems; i++)
+ dialogItems.Add(FarDialogItem());
+ g_StartupInfo.InitDialogItems(&initDialogItems.Front(),
+ &dialogItems.Front(), numDialogItems);
+
+ int maxLen = 0;
+ for (i = 0; i < numLines; i++)
+ {
+ FarDialogItem &dialogItem = dialogItems[1 + i * 2];
+ int len = strlen(dialogItem.Data);
+ if (len > maxLen)
+ maxLen = len;
+ }
+ int maxLen2 = 0;
+ const int kSpace = 10;
+ for (i = 0; i < numLines; i++)
+ {
+ FarDialogItem &dialogItem = dialogItems[1 + i * 2 + 1];
+ int len = strlen(dialogItem.Data);
+ if (len > maxLen2)
+ maxLen2 = len;
+ dialogItem.X1 = maxLen + kSpace;
+ }
+ size = numLines + 6;
+ xSize = maxLen + kSpace + maxLen2 + 5;
+ FarDialogItem &aFirstDialogItem = dialogItems.Front();
+ aFirstDialogItem.Y2 = size - 2;
+ aFirstDialogItem.X2 = xSize - 4;
+
+ int askCode = g_StartupInfo.ShowDialog(xSize, size, NULL, &dialogItems.Front(), numDialogItems);
+ return S_OK;
+}
+
+int CPlugin::ProcessKey(int aKey, unsigned int controlState)
+{
+ if (controlState == PKF_CONTROL && aKey == 'A')
+ {
+ HRESULT result = ShowAttributesWindow();
+ if (result == S_OK)
+ return TRUE;
+ if (result == S_FALSE)
+ return FALSE;
+ throw "Error";
+ }
+ if ((controlState & PKF_ALT) != 0 && aKey == VK_F6)
+ {
+ UString folderPath;
+ if (!NFile::NDirectory::GetOnlyDirPrefix(m_FileName, folderPath))
+ return FALSE;
+ PanelInfo panelInfo;
+ g_StartupInfo.ControlGetActivePanelInfo(panelInfo);
+ GetFilesReal(panelInfo.SelectedItems,
+ panelInfo.SelectedItemsNumber, FALSE,
+ UnicodeStringToMultiByte(folderPath, CP_OEMCP), OPM_SILENT, true);
+ g_StartupInfo.Control(this, FCTL_UPDATEPANEL, NULL);
+ g_StartupInfo.Control(this, FCTL_REDRAWPANEL, NULL);
+ g_StartupInfo.Control(this, FCTL_UPDATEANOTHERPANEL, NULL);
+ g_StartupInfo.Control(this, FCTL_REDRAWANOTHERPANEL, NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/CPP/7zip/UI/Far/Plugin.h b/CPP/7zip/UI/Far/Plugin.h
new file mode 100755
index 00000000..0b617cfb
--- /dev/null
+++ b/CPP/7zip/UI/Far/Plugin.h
@@ -0,0 +1,99 @@
+// 7zip/Far/Plugin.h
+
+#ifndef __7ZIP_FAR_PLUGIN_H
+#define __7ZIP_FAR_PLUGIN_H
+
+#include "Common/MyCom.h"
+
+#include "Windows/COM.h"
+#include "Windows/FileFind.h"
+#include "Windows/PropVariant.h"
+
+#include "../Common/ArchiverInfo.h"
+#include "../Agent/IFolderArchive.h"
+
+#include "FarUtils.h"
+
+class CPlugin
+{
+ NWindows::NCOM::CComInitializer m_ComInitializer;
+ UString m_CurrentDir;
+
+ UString m_PannelTitle;
+
+ InfoPanelLine m_InfoLines[30]; // Change it;
+
+ char m_FileNameBuffer[1024];
+ char m_CurrentDirBuffer[1024];
+ char m_PannelTitleBuffer[1024];
+
+ AString PanelModeColumnTypes;
+ AString PanelModeColumnWidths;
+ PanelMode PanelMode;
+ void AddColumn(PROPID aPropID);
+
+
+ void EnterToDirectory(const UString &aDirName);
+
+ void GetPathParts(UStringVector &aPathParts);
+ void GetCurrentDir();
+public:
+ UString m_FileName;
+ // UString m_DefaultName;
+ NWindows::NFile::NFind::CFileInfoW m_FileInfo;
+
+ CMyComPtr<IInFolderArchive> m_ArchiveHandler;
+ CMyComPtr<IFolderFolder> _folder;
+
+ // CArchiverInfo m_ArchiverInfo;
+ UString _archiveTypeName;
+
+ bool PasswordIsDefined;
+ UString Password;
+
+
+ CPlugin(const UString &fileName,
+ // const UString &aDefaultName,
+ IInFolderArchive *archiveHandler,
+ UString archiveTypeName
+ );
+ ~CPlugin();
+
+ void ReadValueSafe(PROPID aPropID, NWindows::NCOM::CPropVariant aPropVariant);
+ void ReadPluginPanelItem(PluginPanelItem &aPanelItem, UINT32 anItemIndex);
+
+ int GetFindData(PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode);
+ void FreeFindData(PluginPanelItem *PanelItem,int ItemsNumber);
+ int SetDirectory(const char *aDir, int opMode);
+ void GetOpenPluginInfo(struct OpenPluginInfo *anInfo);
+
+ int DeleteFiles(PluginPanelItem *aPanelItems, int itemsNumber, int opMode);
+
+
+ HRESULT ExtractFiles(
+ bool decompressAllItems,
+ const UINT32 *indices,
+ UINT32 numIndices,
+ bool silent,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const UString &destPath,
+ bool passwordIsDefined, const UString &password);
+
+ NFar::NFileOperationReturnCode::EEnum GetFiles(struct PluginPanelItem *aPanelItem, int itemsNumber,
+ int move, char *destPath, int opMode);
+
+ NFar::NFileOperationReturnCode::EEnum GetFilesReal(struct PluginPanelItem *aPanelItems,
+ int itemsNumber, int move, const char *_aDestPath, int opMode, bool aShowBox);
+
+ NFar::NFileOperationReturnCode::EEnum PutFiles(struct PluginPanelItem *aPanelItems, int itemsNumber,
+ int move, int opMode);
+
+ HRESULT ShowAttributesWindow();
+
+ int ProcessKey(int aKey, unsigned int aControlState);
+};
+
+HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &aPluginPanelItems);
+
+#endif
diff --git a/CPP/7zip/UI/Far/PluginCommon.cpp b/CPP/7zip/UI/Far/PluginCommon.cpp
new file mode 100755
index 00000000..3e8e3cee
--- /dev/null
+++ b/CPP/7zip/UI/Far/PluginCommon.cpp
@@ -0,0 +1,50 @@
+// SevenZip/Plugin.cpp
+
+#include "StdAfx.h"
+
+#include "Plugin.h"
+
+/*
+void CPlugin::AddRealIndexOfFile(const CArchiveFolderItem &aFolder,
+ int anIndexInVector, vector<int> &aRealIndexes)
+{
+ const CArchiveFolderFileItem &anItem = aFolder.m_FileSubItems[anIndexInVector];
+ int aHandlerItemIndex = m_ProxyHandler->GetHandlerItemIndex(anItem.m_Properties);
+ if(aHandlerItemIndex < 0)
+ throw "error";
+ aRealIndexes.push_back(aHandlerItemIndex);
+}
+
+void CPlugin::AddRealIndexes(const CArchiveFolderItem &anItem,
+ vector<int> &aRealIndexes)
+{
+ int aHandlerItemIndex = m_ProxyHandler->GetHandlerItemIndex(anItem.m_Properties);
+ if(aHandlerItemIndex >= 0) // test -1 value
+ aRealIndexes.push_back(aHandlerItemIndex);
+ for(int i = 0; i < anItem.m_DirSubItems.Size(); i++)
+ AddRealIndexes(anItem.m_DirSubItems[i], aRealIndexes);
+ for(i = 0; i < anItem.m_FileSubItems.Size(); i++)
+ AddRealIndexOfFile(anItem, i , aRealIndexes);
+}
+
+
+void CPlugin::GetRealIndexes(PluginPanelItem *aPanelItems, int anItemsNumber,
+ vector<int> &aRealIndexes)
+{
+ aRealIndexes.clear();
+ for(int i = 0; i < anItemsNumber; i++)
+ {
+ int anIndex = aPanelItems[i].UserData;
+ if (anIndex < m_FolderItem->m_DirSubItems.Size())
+ {
+ const CArchiveFolderItem &anItem = m_FolderItem->m_DirSubItems[anIndex];
+ AddRealIndexes(anItem, aRealIndexes);
+ }
+ else
+ AddRealIndexOfFile(*m_FolderItem, anIndex - m_FolderItem->m_DirSubItems.Size(),
+ aRealIndexes);
+ }
+ sort(aRealIndexes.begin(), aRealIndexes.end());
+}
+
+*/
diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp
new file mode 100755
index 00000000..6a969c15
--- /dev/null
+++ b/CPP/7zip/UI/Far/PluginDelete.cpp
@@ -0,0 +1,169 @@
+// PluginDelete.cpp
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#include "Plugin.h"
+#include "Messages.h"
+#include "UpdateCallback100.h"
+
+#include "Windows/FileDir.h"
+
+#include "../../Common/FileStreams.h"
+
+#include "Common/StringConvert.h"
+
+#include "../Common/ZipRegistry.h"
+#include "../Common/WorkDir.h"
+
+using namespace NFar;
+using namespace NWindows;
+using namespace NFile;
+using namespace NDirectory;
+
+static LPCWSTR kTempArchivePrefix = L"7zA";
+
+int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems,
+ int opMode)
+{
+ if (numItems == 0)
+ return FALSE;
+ /*
+ if (!m_ArchiverInfo.UpdateEnabled)
+ {
+ g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
+ return FALSE;
+ }
+ */
+ if ((opMode & OPM_SILENT) == 0)
+ {
+ const char *msgItems[]=
+ {
+ g_StartupInfo.GetMsgString(NMessageID::kDeleteTitle),
+ g_StartupInfo.GetMsgString(NMessageID::kDeleteFiles),
+ g_StartupInfo.GetMsgString(NMessageID::kDeleteDelete),
+ g_StartupInfo.GetMsgString(NMessageID::kDeleteCancel)
+ };
+ char msg[1024];
+ if (numItems == 1)
+ {
+ sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteFile),
+ panelItems[0].FindData.cFileName);
+ msgItems[1] = msg;
+ }
+ else if (numItems > 1)
+ {
+ sprintf(msg, g_StartupInfo.GetMsgString(NMessageID::kDeleteNumberOfFiles),
+ numItems);
+ msgItems[1] = msg;
+ }
+ if (g_StartupInfo.ShowMessage(FMSG_WARNING, NULL, msgItems,
+ sizeof(msgItems) / sizeof(msgItems[0]), 2) != 0)
+ return (FALSE);
+ }
+
+ CScreenRestorer screenRestorer;
+ CProgressBox progressBox;
+ CProgressBox *progressBoxPointer = NULL;
+ if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)
+ {
+ screenRestorer.Save();
+
+ progressBoxPointer = &progressBox;
+ progressBox.Init(g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
+ g_StartupInfo.GetMsgString(NMessageID::kDeleting), 1 << 17);
+ }
+
+ NWorkDir::CInfo workDirInfo;
+ ReadWorkDirInfo(workDirInfo);
+
+ UString workDir = GetWorkDir(workDirInfo, m_FileName);
+ CreateComplexDirectory(workDir);
+
+ CTempFileW tempFile;
+ UString tempFileName;
+ if (tempFile.Create(workDir, kTempArchivePrefix, tempFileName) == 0)
+ return FALSE;
+
+
+ CRecordVector<UINT32> indices;
+ indices.Reserve(numItems);
+ for(int i = 0; i < numItems; i++)
+ indices.Add(panelItems[i].UserData);
+
+ ////////////////////////////
+ // Save _folder;
+
+ UStringVector pathVector;
+ GetPathParts(pathVector);
+
+ CMyComPtr<IOutFolderArchive> outArchive;
+ HRESULT result = m_ArchiveHandler.QueryInterface(
+ IID_IOutFolderArchive, &outArchive);
+ if(result != S_OK)
+ {
+ g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
+ return FALSE;
+ }
+ outArchive->SetFolder(_folder);
+
+ CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );
+
+ updateCallbackSpec->Init(m_ArchiveHandler, &progressBox);
+
+
+ result = outArchive->DeleteItems(
+ tempFileName,
+ &indices.Front(), indices.Size(),
+ updateCallback);
+ updateCallback.Release();
+ outArchive.Release();
+
+ if (result != S_OK)
+ {
+ ShowErrorMessage(result);
+ return FALSE;
+ }
+
+ _folder.Release();
+ m_ArchiveHandler->Close();
+
+ if (!DeleteFileAlways(m_FileName))
+ {
+ ShowLastErrorMessage();
+ return FALSE;
+ }
+
+ tempFile.DisableDeleting();
+ if (!MyMoveFile(tempFileName, m_FileName))
+ {
+ ShowLastErrorMessage();
+ return FALSE;
+ }
+
+ result = m_ArchiveHandler->ReOpen(NULL);
+ if (result != S_OK)
+ {
+ ShowErrorMessage(result);
+ return FALSE;
+ }
+
+
+ ////////////////////////////
+ // Restore _folder;
+
+ m_ArchiveHandler->BindToRootFolder(&_folder);
+ for (i = 0; i < pathVector.Size(); i++)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ _folder->BindToFolder(pathVector[i], &newFolder);
+ if(!newFolder )
+ break;
+ _folder = newFolder;
+ }
+ GetCurrentDir();
+
+ return(TRUE);
+}
diff --git a/CPP/7zip/UI/Far/PluginRead.cpp b/CPP/7zip/UI/Far/PluginRead.cpp
new file mode 100755
index 00000000..503ff639
--- /dev/null
+++ b/CPP/7zip/UI/Far/PluginRead.cpp
@@ -0,0 +1,278 @@
+// PluginRead.cpp
+
+#include "StdAfx.h"
+
+#include "Plugin.h"
+
+#include "Messages.h"
+
+#include "Common/StringConvert.h"
+
+#include "Windows/FileName.h"
+#include "Windows/FileFind.h"
+#include "Windows/FileDir.h"
+#include "Windows/Defs.h"
+
+#include "../Common/ZipRegistry.h"
+
+#include "ExtractEngine.h"
+
+using namespace NFar;
+using namespace NWindows;
+
+static const char *kHelpTopicExtrFromSevenZip = "Extract";
+
+static const char kDirDelimiter = '\\';
+
+static const char *kExractPathHistoryName = "7-ZipExtractPath";
+
+HRESULT CPlugin::ExtractFiles(
+ bool decompressAllItems,
+ const UINT32 *indices,
+ UINT32 numIndices,
+ bool silent,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const UString &destPath,
+ bool passwordIsDefined, const UString &password)
+{
+ CScreenRestorer screenRestorer;
+ CProgressBox progressBox;
+ CProgressBox *progressBoxPointer = NULL;
+ if (!silent)
+ {
+ screenRestorer.Save();
+
+ progressBoxPointer = &progressBox;
+ progressBox.Init(g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
+ g_StartupInfo.GetMsgString(NMessageID::kExtracting), 1 << 17);
+ }
+
+
+ CExtractCallBackImp *extractCallbackSpec = new CExtractCallBackImp;
+ CMyComPtr<IFolderArchiveExtractCallback> extractCallback(extractCallbackSpec);
+
+ extractCallbackSpec->Init(
+ CP_OEMCP,
+ progressBoxPointer,
+ /*
+ GetDefaultName(m_FileName, m_ArchiverInfo.Extension),
+ m_FileInfo.LastWriteTime, m_FileInfo.Attributes,
+ */
+ passwordIsDefined, password);
+
+ if (decompressAllItems)
+ return m_ArchiveHandler->Extract(pathMode, overwriteMode,
+ destPath, BoolToInt(false), extractCallback);
+ else
+ {
+ CMyComPtr<IArchiveFolder> archiveFolder;
+ _folder.QueryInterface(IID_IArchiveFolder, &archiveFolder);
+
+ return archiveFolder->Extract(indices, numIndices, pathMode, overwriteMode,
+ destPath, BoolToInt(false), extractCallback);
+ }
+}
+
+NFileOperationReturnCode::EEnum CPlugin::GetFiles(struct PluginPanelItem *panelItems,
+ int itemsNumber, int move, char *_aDestPath, int opMode)
+{
+ return GetFilesReal(panelItems, itemsNumber, move,
+ _aDestPath, opMode, (opMode & OPM_SILENT) == 0);
+}
+
+NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *panelItems,
+ int itemsNumber, int move, const char *_aDestPath, int opMode, bool showBox)
+{
+ if(move != 0)
+ {
+ g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported);
+ return NFileOperationReturnCode::kError;
+ }
+
+ CSysString destPath = _aDestPath;
+ NFile::NName::NormalizeDirPathPrefix(destPath);
+
+ bool extractSelectedFiles = true;
+
+ NExtract::CInfo extractionInfo;
+ extractionInfo.PathMode = NExtract::NPathMode::kCurrentPathnames;
+ extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
+
+ bool silent = (opMode & OPM_SILENT) != 0;
+ bool decompressAllItems = false;
+ UString password = Password;
+ bool passwordIsDefined = PasswordIsDefined;
+
+ if (!silent)
+ {
+ const int kPathIndex = 2;
+
+ ReadExtractionInfo(extractionInfo);
+
+ const int kPathModeRadioIndex = 4;
+ const int kOverwriteModeRadioIndex = kPathModeRadioIndex + 4;
+ const int kNumOverwriteOptions = 6;
+ const int kFilesModeIndex = kOverwriteModeRadioIndex + kNumOverwriteOptions;
+ const int kXSize = 76;
+ const int kYSize = 19;
+ const int kPasswordYPos = 12;
+
+ const int kXMid = kXSize / 2;
+
+ AString oemPassword = UnicodeStringToMultiByte(password, CP_OEMCP);
+
+ struct CInitDialogItem initItems[]={
+ { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kExtractTitle, NULL, NULL },
+ { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, NMessageID::kExtractTo, NULL, NULL },
+
+ { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, DIF_HISTORY, false, -1, destPath, kExractPathHistoryName},
+ // { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, 0, false, -1, destPath, NULL},
+
+ { DI_SINGLEBOX, 4, 5, kXMid - 2, 5 + 4, false, false, 0, false, NMessageID::kExtractPathMode, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 6, 0, 0, false,
+ extractionInfo.PathMode == NExtract::NPathMode::kFullPathnames,
+ DIF_GROUP, false, NMessageID::kExtractPathFull, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 7, 0, 0, false,
+ extractionInfo.PathMode == NExtract::NPathMode::kCurrentPathnames,
+ 0, false, NMessageID::kExtractPathCurrent, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 8, 0, 0, false,
+ extractionInfo.PathMode == NExtract::NPathMode::kNoPathnames,
+ false, 0, NMessageID::kExtractPathNo, NULL, NULL },
+
+ { DI_SINGLEBOX, kXMid, 5, kXSize - 6, 5 + kNumOverwriteOptions, false, false, 0, false, NMessageID::kExtractOwerwriteMode, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false,
+ extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAskBefore,
+ DIF_GROUP, false, NMessageID::kExtractOwerwriteAsk, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false,
+ extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kWithoutPrompt,
+ 0, false, NMessageID::kExtractOwerwritePrompt, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false,
+ extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kSkipExisting,
+ 0, false, NMessageID::kExtractOwerwriteSkip, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 9, 0, 0, false,
+ extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAutoRename,
+ 0, false, NMessageID::kExtractOwerwriteAutoRename, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 10, 0, 0, false,
+ extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting,
+ 0, false, NMessageID::kExtractOwerwriteAutoRenameExisting, NULL, NULL },
+
+ { DI_SINGLEBOX, 4, 10, kXMid- 2, 10 + 3, false, false, 0, false, NMessageID::kExtractFilesMode, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 11, 0, 0, false, true, DIF_GROUP, false, NMessageID::kExtractFilesSelected, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 12, 0, 0, false, false, 0, false, NMessageID::kExtractFilesAll, NULL, NULL },
+
+ { DI_SINGLEBOX, kXMid, kPasswordYPos, kXSize - 6, kPasswordYPos + 2, false, false, 0, false, NMessageID::kExtractPassword, NULL, NULL },
+ { DI_PSWEDIT, kXMid + 2, kPasswordYPos + 1, kXSize - 8, 12, false, false, 0, false, -1, oemPassword, NULL},
+
+ { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL },
+
+
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kExtractExtract, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kExtractCancel, NULL, NULL }
+ };
+
+ const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);
+ const int kOkButtonIndex = kNumDialogItems - 2;
+ const int kPasswordIndex = kNumDialogItems - 4;
+
+ FarDialogItem dialogItems[kNumDialogItems];
+ g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
+ for (;;)
+ {
+ int askCode = g_StartupInfo.ShowDialog(kXSize, kYSize,
+ kHelpTopicExtrFromSevenZip, dialogItems, kNumDialogItems);
+ if (askCode != kOkButtonIndex)
+ return NFileOperationReturnCode::kInterruptedByUser;
+ destPath = dialogItems[kPathIndex].Data;
+ destPath.Trim();
+ if (destPath.IsEmpty())
+ {
+ if(!NFile::NDirectory::MyGetCurrentDirectory(destPath))
+ throw 318016;
+ NFile::NName::NormalizeDirPathPrefix(destPath);
+ break;
+ }
+ else
+ {
+ if(destPath[destPath.Length() - 1] == kDirDelimiter)
+ break;
+ }
+ g_StartupInfo.ShowMessage("You must specify directory path");
+ }
+
+ if (dialogItems[kPathModeRadioIndex].Selected)
+ extractionInfo.PathMode = NExtract::NPathMode::kFullPathnames;
+ else if (dialogItems[kPathModeRadioIndex + 1].Selected)
+ extractionInfo.PathMode = NExtract::NPathMode::kCurrentPathnames;
+ else if (dialogItems[kPathModeRadioIndex + 2].Selected)
+ extractionInfo.PathMode = NExtract::NPathMode::kNoPathnames;
+ else
+ throw 31806;
+
+ if (dialogItems[kOverwriteModeRadioIndex].Selected)
+ extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
+ else if (dialogItems[kOverwriteModeRadioIndex + 1].Selected)
+ extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
+ else if (dialogItems[kOverwriteModeRadioIndex + 2].Selected)
+ extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kSkipExisting;
+ else if (dialogItems[kOverwriteModeRadioIndex + 3].Selected)
+ extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAutoRename;
+ else if (dialogItems[kOverwriteModeRadioIndex + 4].Selected)
+ extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAutoRenameExisting;
+ else
+ throw 31806;
+
+ if (dialogItems[kFilesModeIndex].Selected)
+ decompressAllItems = false;
+ else if (dialogItems[kFilesModeIndex + 1].Selected)
+ decompressAllItems = true;
+ else
+ throw 31806;
+
+ SaveExtractionInfo(extractionInfo);
+
+ if (dialogItems[kFilesModeIndex].Selected)
+ extractSelectedFiles = true;
+ else if (dialogItems[kFilesModeIndex + 1].Selected)
+ extractSelectedFiles = false;
+ else
+ throw 31806;
+
+ oemPassword = dialogItems[kPasswordIndex].Data;
+ password = MultiByteToUnicodeString(oemPassword, CP_OEMCP);
+ passwordIsDefined = !password.IsEmpty();
+ }
+
+ NFile::NDirectory::CreateComplexDirectory(destPath);
+
+ /*
+ vector<int> realIndices;
+ if (!decompressAllItems)
+ GetRealIndexes(panelItems, itemsNumber, realIndices);
+ */
+ CRecordVector<UINT32> indices;
+ indices.Reserve(itemsNumber);
+ for (int i = 0; i < itemsNumber; i++)
+ indices.Add(panelItems[i].UserData);
+
+ HRESULT result = ExtractFiles(decompressAllItems, &indices.Front(), itemsNumber,
+ !showBox, extractionInfo.PathMode, extractionInfo.OverwriteMode,
+ MultiByteToUnicodeString(destPath, CP_OEMCP),
+ passwordIsDefined, password);
+ // HRESULT result = ExtractFiles(decompressAllItems, realIndices, !showBox,
+ // extractionInfo, destPath, passwordIsDefined, password);
+ if (result != S_OK)
+ {
+ if (result == E_ABORT)
+ return NFileOperationReturnCode::kInterruptedByUser;
+ ShowErrorMessage(result);
+ return NFileOperationReturnCode::kError;
+ }
+
+ // if(move != 0)
+ // {
+ // if(DeleteFiles(panelItems, itemsNumber, opMode) == FALSE)
+ // return NFileOperationReturnCode::kError;
+ // }
+ return NFileOperationReturnCode::kSuccess;
+}
diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp
new file mode 100755
index 00000000..d6730985
--- /dev/null
+++ b/CPP/7zip/UI/Far/PluginWrite.cpp
@@ -0,0 +1,696 @@
+// PluginWrite.cpp
+
+#include "StdAfx.h"
+
+#include "Plugin.h"
+
+#include "Common/StringConvert.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/FileName.h"
+#include "Windows/FileFind.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+
+#include "../Common/ZipRegistry.h"
+#include "../Common/WorkDir.h"
+#include "../Common/OpenArchive.h"
+
+#include "../Agent/Agent.h"
+
+#include "ProgressBox.h"
+#include "Messages.h"
+#include "UpdateCallback100.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDirectory;
+using namespace NFar;
+
+using namespace NUpdateArchive;
+
+static const char *kHelpTopic = "Update";
+
+static LPCWSTR kTempArcivePrefix = L"7zA";
+
+static const char *kArchiveHistoryKeyName = "7-ZipArcName";
+
+static UINT32 g_MethodMap[] = { 0, 1, 3, 5, 7, 9 };
+
+static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UINT32 method)
+{
+ CMyComPtr<ISetProperties> setProperties;
+ if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK)
+ {
+ UStringVector realNames;
+ realNames.Add(UString(L"x"));
+ NCOM::CPropVariant value = (UInt32)method;
+ CRecordVector<const wchar_t *> names;
+ for(int i = 0; i < realNames.Size(); i++)
+ names.Add(realNames[i]);
+ RINOK(setProperties->SetProperties(&names.Front(), &value, names.Size()));
+ }
+ return S_OK;
+}
+
+NFileOperationReturnCode::EEnum CPlugin::PutFiles(
+ struct PluginPanelItem *panelItems, int numItems,
+ int moveMode, int opMode)
+{
+ if(moveMode != 0)
+ {
+ g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported);
+ return NFileOperationReturnCode::kError;
+ }
+ if (numItems == 0)
+ return NFileOperationReturnCode::kError;
+
+ /*
+ if (!m_ArchiverInfo.UpdateEnabled)
+ {
+ g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
+ return NFileOperationReturnCode::kError;
+ }
+ */
+
+ const int kYSize = 14;
+ const int kXMid = 38;
+
+ NCompression::CInfo compressionInfo;
+ ReadCompressionInfo(compressionInfo);
+
+ int methodIndex = 0;
+ for (int i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--)
+ if (compressionInfo.Level >= g_MethodMap[i])
+ {
+ methodIndex = i;
+ break;
+ }
+
+ const int kMethodRadioIndex = 2;
+ const int kModeRadioIndex = kMethodRadioIndex + 7;
+
+ struct CInitDialogItem initItems[]={
+ { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL },
+ { DI_SINGLEBOX, 4, 2, kXMid - 2, 2 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 3, 0, 0, methodIndex == 0, methodIndex == 0,
+ DIF_GROUP, false, NMessageID::kUpdateMethodStore, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 4, 0, 0, methodIndex == 1, methodIndex == 1,
+ 0, false, NMessageID::kUpdateMethodFastest, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 5, 0, 0, methodIndex == 2, methodIndex == 2,
+ 0, false, NMessageID::kUpdateMethodFast, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 6, 0, 0, methodIndex == 3, methodIndex == 3,
+ 0, false, NMessageID::kUpdateMethodNormal, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 7, 0, 0, methodIndex == 4, methodIndex == 4,
+ 0, false, NMessageID::kUpdateMethodMaximum, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 8, 0, 0, methodIndex == 5, methodIndex == 5,
+ 0, false, NMessageID::kUpdateMethodUltra, NULL, NULL },
+
+ { DI_SINGLEBOX, kXMid, 2, 70, 2 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 3, 0, 0, false, true,
+ DIF_GROUP, false, NMessageID::kUpdateModeAdd, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 4, 0, 0, false, false,
+ 0, false, NMessageID::kUpdateModeUpdate, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false, false,
+ 0, false, NMessageID::kUpdateModeFreshen, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, false,
+ 0, false, NMessageID::kUpdateModeSynchronize, NULL, NULL },
+
+ { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL },
+
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kUpdateAdd, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL }
+ };
+
+ const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);
+ const int kOkButtonIndex = kNumDialogItems - 2;
+ FarDialogItem dialogItems[kNumDialogItems];
+ g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
+ int askCode = g_StartupInfo.ShowDialog(76, kYSize,
+ kHelpTopic, dialogItems, kNumDialogItems);
+ if (askCode != kOkButtonIndex)
+ return NFileOperationReturnCode::kInterruptedByUser;
+
+ compressionInfo.Level = g_MethodMap[0];
+ for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++)
+ if (dialogItems[kMethodRadioIndex + i].Selected)
+ compressionInfo.Level = g_MethodMap[i];
+
+ const CActionSet *actionSet;
+
+ if (dialogItems[kModeRadioIndex].Selected)
+ actionSet = &kAddActionSet;
+ else if (dialogItems[kModeRadioIndex + 1].Selected)
+ actionSet = &kUpdateActionSet;
+ else if (dialogItems[kModeRadioIndex + 2].Selected)
+ actionSet = &kFreshActionSet;
+ else if (dialogItems[kModeRadioIndex + 3].Selected)
+ actionSet = &kSynchronizeActionSet;
+ else
+ throw 51751;
+
+ SaveCompressionInfo(compressionInfo);
+
+ NWorkDir::CInfo workDirInfo;
+ ReadWorkDirInfo(workDirInfo);
+ UString workDir = GetWorkDir(workDirInfo, m_FileName);
+ CreateComplexDirectory(workDir);
+
+ CTempFileW tempFile;
+ UString tempFileName;
+ if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0)
+ return NFileOperationReturnCode::kError;
+
+
+ /*
+ CSysStringVector fileNames;
+ for(int i = 0; i < numItems; i++)
+ {
+ const PluginPanelItem &panelItem = panelItems[i];
+ CSysString fullName;
+ if (!MyGetFullPathName(panelItem.FindData.cFileName, fullName))
+ return NFileOperationReturnCode::kError;
+ fileNames.Add(fullName);
+ }
+ */
+
+ CScreenRestorer screenRestorer;
+ CProgressBox progressBox;
+ CProgressBox *progressBoxPointer = NULL;
+ if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)
+ {
+ screenRestorer.Save();
+
+ progressBoxPointer = &progressBox;
+ progressBox.Init(g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
+ g_StartupInfo.GetMsgString(NMessageID::kUpdating), 1 << 16);
+ }
+
+ ////////////////////////////
+ // Save FolderItem;
+ UStringVector aPathVector;
+ GetPathParts(aPathVector);
+
+ /*
+ UString anArchivePrefix;
+ for(i = aPathVector.Size() - 1; i >= 0; i--)
+ {
+ anArchivePrefix += aPathVector[i];
+ anArchivePrefix += wchar_t(NName::kDirDelimiter);
+ }
+ /////////////////////////////////
+ */
+
+ UStringVector fileNames;
+ fileNames.Reserve(numItems);
+ for(i = 0; i < numItems; i++)
+ fileNames.Add(MultiByteToUnicodeString(panelItems[i].FindData.cFileName, CP_OEMCP));
+ CRecordVector<const wchar_t *> fileNamePointers;
+ fileNamePointers.Reserve(numItems);
+ for(i = 0; i < numItems; i++)
+ fileNamePointers.Add(fileNames[i]);
+
+ CMyComPtr<IOutFolderArchive> outArchive;
+ HRESULT result = m_ArchiveHandler.QueryInterface(IID_IOutFolderArchive, &outArchive);
+ if(result != S_OK)
+ {
+ g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
+ return NFileOperationReturnCode::kError;
+ }
+ outArchive->SetFolder(_folder);
+
+ // CSysString aCurrentFolder;
+ // MyGetCurrentDirectory(aCurrentFolder);
+ // outArchive->SetFiles(MultiByteToUnicodeString(aCurrentFolder, CP_OEMCP),
+ outArchive->SetFiles(L"",
+ &fileNamePointers.Front(), fileNamePointers.Size());
+ BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues];
+ for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
+ actionSetByte[i] = actionSet->StateActions[i];
+
+ CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );
+
+ updateCallbackSpec->Init(m_ArchiveHandler, &progressBox);
+
+ if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK)
+ return NFileOperationReturnCode::kError;
+
+ result = outArchive->DoOperation(NULL, NULL,
+ tempFileName, actionSetByte, NULL, updateCallback);
+ updateCallback.Release();
+ outArchive.Release();
+
+ /*
+ HRESULT result = Compress(fileNames, anArchivePrefix, *actionSet,
+ m_ProxyHandler.get(),
+ m_ArchiverInfo.ClassID, compressionInfo.Method == 0,
+ compressionInfo.Method == 2, tempFileName, progressBoxPointer);
+ */
+
+ if (result != S_OK)
+ {
+ ShowErrorMessage(result);
+ return NFileOperationReturnCode::kError;
+ }
+
+ _folder.Release();
+ m_ArchiveHandler->Close();
+
+ // m_FolderItem = NULL;
+
+ if (!DeleteFileAlways(m_FileName))
+ {
+ ShowLastErrorMessage();
+ return NFileOperationReturnCode::kError;
+ }
+
+ tempFile.DisableDeleting();
+ if (!MyMoveFile(tempFileName, m_FileName))
+ {
+ ShowLastErrorMessage();
+ return NFileOperationReturnCode::kError;
+ }
+
+ m_ArchiveHandler->ReOpen(NULL);
+ if (result != S_OK)
+ {
+ ShowErrorMessage(result);
+ return NFileOperationReturnCode::kError;
+ }
+
+ /*
+ if(m_ProxyHandler->ReInit(NULL) != S_OK)
+ return NFileOperationReturnCode::kError;
+ */
+
+ ////////////////////////////
+ // Restore FolderItem;
+
+ m_ArchiveHandler->BindToRootFolder(&_folder);
+ for (i = 0; i < aPathVector.Size(); i++)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ _folder->BindToFolder(aPathVector[i], &newFolder);
+ if(!newFolder )
+ break;
+ _folder = newFolder;
+ }
+
+ /*
+ if(moveMode != 0)
+ {
+ for(int i = 0; i < numItems; i++)
+ {
+ const PluginPanelItem &aPluginPanelItem = panelItems[i];
+ bool result;
+ if(NFile::NFind::NAttributes::IsDirectory(aPluginPanelItem.FindData.dwFileAttributes))
+ result = NFile::NDirectory::RemoveDirectoryWithSubItems(
+ aPluginPanelItem.FindData.cFileName);
+ else
+ result = NFile::NDirectory::DeleteFileAlways(
+ aPluginPanelItem.FindData.cFileName);
+ if(!result)
+ return NFileOperationReturnCode::kError;
+ }
+ }
+ */
+ return NFileOperationReturnCode::kSuccess;
+}
+
+
+
+/*
+// {23170F69-40C1-278A-1000-000100030000}
+DEFINE_GUID(CLSID_CAgentArchiveHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00);
+*/
+
+HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
+{
+ if (pluginPanelItems.Size() == 0)
+ return E_FAIL;
+
+ UStringVector fileNames;
+ for(int i = 0; i < pluginPanelItems.Size(); i++)
+ {
+ const PluginPanelItem &panelItem = pluginPanelItems[i];
+ CSysString fullName;
+ if (strcmp(panelItem.FindData.cFileName, "..") == 0 &&
+ NFind::NAttributes::IsDirectory(panelItem.FindData.dwFileAttributes))
+ return E_FAIL;
+ if (strcmp(panelItem.FindData.cFileName, ".") == 0 &&
+ NFind::NAttributes::IsDirectory(panelItem.FindData.dwFileAttributes))
+ return E_FAIL;
+ if (!MyGetFullPathName(panelItem.FindData.cFileName, fullName))
+ return E_FAIL;
+ fileNames.Add(MultiByteToUnicodeString(fullName, CP_OEMCP));
+ }
+
+ NCompression::CInfo compressionInfo;
+ // CZipRegistryManager aZipRegistryManager;
+ ReadCompressionInfo(compressionInfo);
+
+ int archiverIndex = 0;
+
+ CObjectVector<CArchiverInfo> archiverInfoList;
+ {
+ CObjectVector<CArchiverInfo> fullArchiverInfoList;
+ ReadArchiverInfoList(fullArchiverInfoList);
+ for (int i = 0; i < fullArchiverInfoList.Size(); i++)
+ {
+ const CArchiverInfo &archiverInfo = fullArchiverInfoList[i];
+ if (archiverInfo.UpdateEnabled)
+ {
+ if (archiverInfo.Name.CompareNoCase(compressionInfo.ArchiveType) == 0)
+ archiverIndex = archiverInfoList.Size();
+ archiverInfoList.Add(archiverInfo);
+ }
+ }
+ }
+ if (archiverInfoList.IsEmpty())
+ throw "There is no update achivers";
+
+
+ UString resultPath;
+ {
+ NName::CParsedPath parsedPath;
+ parsedPath.ParsePath(fileNames.Front());
+ if(parsedPath.PathParts.Size() == 0)
+ return E_FAIL;
+ if (fileNames.Size() == 1 || parsedPath.PathParts.Size() == 1)
+ {
+ // CSysString pureName, dot, extension;
+ resultPath = parsedPath.PathParts.Back();
+ }
+ else
+ {
+ parsedPath.PathParts.DeleteBack();
+ resultPath = parsedPath.PathParts.Back();
+ }
+ }
+ UString archiveNameSrc = resultPath;
+ UString archiveName = archiveNameSrc;
+
+ const CArchiverInfo &archiverInfo = archiverInfoList[archiverIndex];
+ int prevFormat = archiverIndex;
+
+ if (!archiverInfo.KeepName)
+ {
+ int dotPos = archiveName.ReverseFind('.');
+ int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/'));
+ if (dotPos > slashPos)
+ archiveName = archiveName.Left(dotPos);
+ }
+ archiveName += L'.';
+ archiveName += archiverInfo.GetMainExtension();
+
+ const CActionSet *actionSet = &kAddActionSet;
+
+ for (;;)
+ {
+ AString archiveNameA = UnicodeStringToMultiByte(archiveName, CP_OEMCP);
+ const int kYSize = 16;
+ const int kXMid = 38;
+
+ const int kArchiveNameIndex = 2;
+ const int kMethodRadioIndex = kArchiveNameIndex + 2;
+ const int kModeRadioIndex = kMethodRadioIndex + 7;
+
+ const CArchiverInfo &archiverInfo = archiverInfoList[archiverIndex];
+
+ char updateAddToArchiveString[512];
+ sprintf(updateAddToArchiveString,
+ g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive), GetSystemString(archiverInfo.Name), CP_OEMCP);
+
+ int methodIndex = 0;
+ for (int i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--)
+ if (compressionInfo.Level >= g_MethodMap[i])
+ {
+ methodIndex = i;
+ break;
+ }
+
+ struct CInitDialogItem initItems[]=
+ {
+ { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL },
+
+ { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, updateAddToArchiveString, NULL },
+
+ { DI_EDIT, 5, 3, 70, 3, true, false, DIF_HISTORY, false, -1, archiveNameA, kArchiveHistoryKeyName},
+ // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, archiveName, NULL},
+
+ { DI_SINGLEBOX, 4, 4, kXMid - 2, 4 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 5, 0, 0, false, methodIndex == 0,
+ DIF_GROUP, false, NMessageID::kUpdateMethodStore, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 6, 0, 0, false, methodIndex == 1,
+ 0, false, NMessageID::kUpdateMethodFastest, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 7, 0, 0, false, methodIndex == 2,
+ 0, false, NMessageID::kUpdateMethodFast, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 8, 0, 0, false, methodIndex == 3,
+ 0, false, NMessageID::kUpdateMethodNormal, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 9, 0, 0, false, methodIndex == 4,
+ false, 0, NMessageID::kUpdateMethodMaximum, NULL, NULL },
+ { DI_RADIOBUTTON, 6, 10, 0, 0, false, methodIndex == 5,
+ false, 0, NMessageID::kUpdateMethodUltra, NULL, NULL },
+
+ { DI_SINGLEBOX, kXMid, 4, 70, 4 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false,
+ actionSet == &kAddActionSet,
+ DIF_GROUP, false, NMessageID::kUpdateModeAdd, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false,
+ actionSet == &kUpdateActionSet,
+ 0, false, NMessageID::kUpdateModeUpdate, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false,
+ actionSet == &kFreshActionSet,
+ 0, false, NMessageID::kUpdateModeFreshen, NULL, NULL },
+ { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false,
+ actionSet == &kSynchronizeActionSet,
+ 0, false, NMessageID::kUpdateModeSynchronize, NULL, NULL },
+
+ { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL },
+
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kUpdateAdd, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kUpdateSelectArchiver, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL }
+ };
+
+ const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);
+
+ const int kOkButtonIndex = kNumDialogItems - 3;
+ const int kSelectarchiverButtonIndex = kNumDialogItems - 2;
+
+ FarDialogItem dialogItems[kNumDialogItems];
+ g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
+ int askCode = g_StartupInfo.ShowDialog(76, kYSize,
+ kHelpTopic, dialogItems, kNumDialogItems);
+
+ archiveNameA = dialogItems[kArchiveNameIndex].Data;
+ archiveNameA.Trim();
+ archiveName = MultiByteToUnicodeString(archiveNameA, CP_OEMCP);
+
+ compressionInfo.Level = g_MethodMap[0];
+ for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++)
+ if (dialogItems[kMethodRadioIndex + i].Selected)
+ compressionInfo.Level = g_MethodMap[i];
+
+ if (dialogItems[kModeRadioIndex].Selected)
+ actionSet = &kAddActionSet;
+ else if (dialogItems[kModeRadioIndex + 1].Selected)
+ actionSet = &kUpdateActionSet;
+ else if (dialogItems[kModeRadioIndex + 2].Selected)
+ actionSet = &kFreshActionSet;
+ else if (dialogItems[kModeRadioIndex + 3].Selected)
+ actionSet = &kSynchronizeActionSet;
+ else
+ throw 51751;
+
+ if (askCode == kSelectarchiverButtonIndex)
+ {
+ CSysStringVector archiverNames;
+ for(int i = 0; i < archiverInfoList.Size(); i++)
+ archiverNames.Add(GetSystemString(archiverInfoList[i].Name,
+ CP_OEMCP));
+
+ int index = g_StartupInfo.Menu(FMENU_AUTOHIGHLIGHT,
+ g_StartupInfo.GetMsgString(NMessageID::kUpdateSelectArchiverMenuTitle),
+ NULL, archiverNames, archiverIndex);
+ if(index >= 0)
+ {
+ const CArchiverInfo &prevArchiverInfo = archiverInfoList[prevFormat];
+ if (prevArchiverInfo.KeepName)
+ {
+ const UString &prevExtension = prevArchiverInfo.GetMainExtension();
+ const int prevExtensionLen = prevExtension.Length();
+ if (archiveName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0)
+ {
+ int pos = archiveName.Length() - prevExtensionLen;
+ UString temp = archiveName.Left(pos);
+ if (pos > 1)
+ {
+ int dotPos = archiveName.ReverseFind('.');
+ if (dotPos == pos - 1)
+ archiveName = archiveName.Left(dotPos);
+ }
+ }
+ }
+
+ archiverIndex = index;
+ const CArchiverInfo &archiverInfo =
+ archiverInfoList[archiverIndex];
+ prevFormat = archiverIndex;
+
+ if (archiverInfo.KeepName)
+ archiveName = archiveNameSrc;
+ else
+ {
+ int dotPos = archiveName.ReverseFind('.');
+ int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/'));
+ if (dotPos > slashPos)
+ archiveName = archiveName.Left(dotPos);
+ }
+ archiveName += L'.';
+ archiveName += archiverInfo.GetMainExtension();
+ }
+ continue;
+ }
+
+ if (askCode != kOkButtonIndex)
+ return E_ABORT;
+
+ break;
+ }
+
+ const CArchiverInfo &archiverInfoFinal = archiverInfoList[archiverIndex];
+ compressionInfo.ArchiveType = archiverInfoFinal.Name;
+ SaveCompressionInfo(compressionInfo);
+
+ NWorkDir::CInfo workDirInfo;
+ ReadWorkDirInfo(workDirInfo);
+
+ UString fullArchiveName;
+ if (!MyGetFullPathName(archiveName, fullArchiveName))
+ return E_FAIL;
+
+ UString workDir = GetWorkDir(workDirInfo, fullArchiveName);
+ CreateComplexDirectory(workDir);
+
+ CTempFileW tempFile;
+ UString tempFileName;
+ if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0)
+ return E_FAIL;
+
+
+ CScreenRestorer screenRestorer;
+ CProgressBox progressBox;
+ CProgressBox *progressBoxPointer = NULL;
+
+ screenRestorer.Save();
+
+ progressBoxPointer = &progressBox;
+ progressBox.Init(g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
+ g_StartupInfo.GetMsgString(NMessageID::kUpdating), 1 << 16);
+
+
+ NFind::CFileInfoW fileInfo;
+
+ CMyComPtr<IOutFolderArchive> outArchive;
+
+ CMyComPtr<IInFolderArchive> archiveHandler;
+ if(NFind::FindFile(fullArchiveName, fileInfo))
+ {
+ if (fileInfo.IsDirectory())
+ throw "There is Directory with such name";
+
+ CAgent *agentSpec = new CAgent;
+ archiveHandler = agentSpec;
+ // CLSID realClassID;
+ CMyComBSTR archiveType;
+ RINOK(agentSpec->Open(
+ GetUnicodeString(fullArchiveName, CP_OEMCP),
+ // &realClassID,
+ &archiveType,
+ NULL));
+
+ if (archiverInfoFinal.Name.CompareNoCase((const wchar_t *)archiveType) != 0)
+ throw "Type of existing archive differs from specified type";
+ HRESULT result = archiveHandler.QueryInterface(
+ IID_IOutFolderArchive, &outArchive);
+ if(result != S_OK)
+ {
+ g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
+ return E_FAIL;
+ }
+ }
+ else
+ {
+ // HRESULT result = outArchive.CoCreateInstance(classID);
+ CAgent *agentSpec = new CAgent;
+ outArchive = agentSpec;
+
+ /*
+ HRESULT result = outArchive.CoCreateInstance(CLSID_CAgentArchiveHandler);
+ if (result != S_OK)
+ {
+ g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
+ return E_FAIL;
+ }
+ */
+ }
+
+ CRecordVector<const wchar_t *> fileNamePointers;
+ fileNamePointers.Reserve(fileNames.Size());
+ for(i = 0; i < fileNames.Size(); i++)
+ fileNamePointers.Add(fileNames[i]);
+
+ outArchive->SetFolder(NULL);
+ // CSysString aCurrentFolder;
+ // MyGetCurrentDirectory(aCurrentFolder);
+ // outArchive->SetFiles(MultiByteToUnicodeString(aCurrentFolder, CP_OEMCP),
+ outArchive->SetFiles(L"",
+ &fileNamePointers.Front(), fileNamePointers.Size());
+ BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues];
+ for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
+ actionSetByte[i] = actionSet->StateActions[i];
+
+ CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );
+
+ updateCallbackSpec->Init(archiveHandler, &progressBox);
+
+
+ RINOK(SetOutProperties(outArchive, compressionInfo.Level));
+
+ HRESULT result = outArchive->DoOperation(
+ GetUnicodeString(archiverInfoFinal.FilePath, CP_OEMCP),
+ &archiverInfoFinal.ClassID,
+ tempFileName, actionSetByte,
+ NULL, updateCallback);
+ updateCallback.Release();
+ outArchive.Release();
+
+ if (result != S_OK)
+ {
+ ShowErrorMessage(result);
+ return result;
+ }
+
+ if(archiveHandler)
+ {
+ archiveHandler->Close();
+ if (!DeleteFileAlways(fullArchiveName))
+ {
+ ShowLastErrorMessage();
+ return NFileOperationReturnCode::kError;
+ }
+ }
+ tempFile.DisableDeleting();
+ if (!MyMoveFile(tempFileName, fullArchiveName))
+ {
+ ShowLastErrorMessage();
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
+
diff --git a/CPP/7zip/UI/Far/ProgressBox.cpp b/CPP/7zip/UI/Far/ProgressBox.cpp
new file mode 100755
index 00000000..64e0e09d
--- /dev/null
+++ b/CPP/7zip/UI/Far/ProgressBox.cpp
@@ -0,0 +1,103 @@
+// ProgressBox.cpp
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#include "ProgressBox.h"
+
+#include "FarUtils.h"
+
+using namespace NFar;
+
+static void CopySpaces(char *destString, int numSpaces)
+{
+ for(int i = 0; i < numSpaces; i++)
+ destString[i] = ' ';
+ destString[i] = '\0';
+}
+
+/////////////////////////////////
+// CMessageBox
+
+const int kNumStringsMax = 10;
+
+void CMessageBox::Init(const CSysString &title, const CSysString &message,
+ int numStrings, int width)
+{
+ if (numStrings > kNumStringsMax)
+ throw 120620;
+ m_NumStrings = numStrings;
+ m_Width = width;
+
+ m_Title = title;
+ m_Message = message;
+}
+
+const int kNumStaticStrings = 2;
+
+void CMessageBox::ShowProcessMessages(const char *messages[])
+{
+ const char *msgItems[kNumStaticStrings + kNumStringsMax];
+ msgItems[0] = m_Title;
+ msgItems[1] = m_Message;
+
+ char formattedMessages[kNumStringsMax][256];
+
+ for (int i = 0; i < m_NumStrings; i++)
+ {
+ char *formattedMessage = formattedMessages[i];
+ int len = strlen(messages[i]);
+ int size = MyMax(m_Width, len);
+ int startPos = (size - len) / 2;
+ CopySpaces(formattedMessage, startPos);
+ strcpy(formattedMessage + startPos, messages[i]);
+ CopySpaces(formattedMessage + startPos + len, size - startPos - len);
+ msgItems[kNumStaticStrings + i] = formattedMessage;
+ }
+
+ g_StartupInfo.ShowMessage(0, NULL, msgItems, kNumStaticStrings + m_NumStrings, 0);
+}
+
+/////////////////////////////////
+// CProgressBox
+
+void CProgressBox::Init(const CSysString &title, const CSysString &message,
+ UInt64 step)
+{
+ CMessageBox::Init(title, message, 1, 22);
+ m_Step = step;
+ m_CompletedPrev = 0;
+ m_Total = 0;
+}
+
+
+void CProgressBox::ShowProcessMessage(const char *message)
+{
+ CMessageBox::ShowProcessMessages(&message);
+}
+
+void CProgressBox::PrintPercent(UInt64 percent)
+{
+ char valueBuffer[32];
+ sprintf(valueBuffer, "%I64u%%", percent);
+ ShowProcessMessage(valueBuffer);
+}
+
+void CProgressBox::SetTotal(UInt64 total)
+{
+ m_Total = total;
+}
+
+void CProgressBox::PrintCompeteValue(UInt64 completed)
+{
+ if (completed >= m_CompletedPrev + m_Step || completed < m_CompletedPrev ||
+ completed == 0)
+ {
+ if (m_Total == 0)
+ PrintPercent(0);
+ else
+ PrintPercent(completed * 100 / m_Total);
+ m_CompletedPrev = completed;
+ }
+}
diff --git a/CPP/7zip/UI/Far/ProgressBox.h b/CPP/7zip/UI/Far/ProgressBox.h
new file mode 100755
index 00000000..8721b456
--- /dev/null
+++ b/CPP/7zip/UI/Far/ProgressBox.h
@@ -0,0 +1,35 @@
+// ProgressBox.h
+
+#ifndef __PROGRESSBOX_H
+#define __PROGRESSBOX_H
+
+#include "Common/String.h"
+#include "Common/Types.h"
+
+class CMessageBox
+{
+ CSysString m_Title;
+ CSysString m_Message;
+ int m_NumStrings;
+ int m_Width;
+public:
+ void Init(const CSysString &title,
+ const CSysString &message, int numStrings, int width);
+ void ShowProcessMessages(const char *messages[]);
+};
+
+class CProgressBox: public CMessageBox
+{
+ UInt64 m_Total;
+ UInt64 m_CompletedPrev;
+ UInt64 m_Step;
+public:
+ void Init(const CSysString &title,
+ const CSysString &message, UInt64 step);
+ void ShowProcessMessage(const char *message);
+ void PrintPercent(UInt64 percent);
+ void PrintCompeteValue(UInt64 completed);
+ void SetTotal(UInt64 total);
+};
+
+#endif
diff --git a/CPP/7zip/UI/Far/StdAfx.cpp b/CPP/7zip/UI/Far/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/UI/Far/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/UI/Far/StdAfx.h b/CPP/7zip/UI/Far/StdAfx.h
new file mode 100755
index 00000000..0a7c347b
--- /dev/null
+++ b/CPP/7zip/UI/Far/StdAfx.h
@@ -0,0 +1,12 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include <windows.h>
+#include <stdio.h>
+
+#include "Common/NewHandler.h"
+
+#endif
+
diff --git a/CPP/7zip/UI/Far/UpdateCallback100.cpp b/CPP/7zip/UI/Far/UpdateCallback100.cpp
new file mode 100755
index 00000000..f1a2946e
--- /dev/null
+++ b/CPP/7zip/UI/Far/UpdateCallback100.cpp
@@ -0,0 +1,54 @@
+// UpdateCallback.h
+
+#include "StdAfx.h"
+
+#include "UpdateCallback100.h"
+
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+#include "FarUtils.h"
+
+using namespace NFar;
+
+STDMETHODIMP CUpdateCallback100Imp::SetTotal(UINT64 aSize)
+{
+ if (m_ProgressBox != 0)
+ {
+ m_ProgressBox->SetTotal(aSize);
+ m_ProgressBox->PrintCompeteValue(0);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UINT64 *aCompleteValue)
+{
+ if(WasEscPressed())
+ return E_ABORT;
+ if (m_ProgressBox != 0 && aCompleteValue != NULL)
+ m_ProgressBox->PrintCompeteValue(*aCompleteValue);
+ return S_OK;
+}
+
+STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t *aName)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t *aName)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CUpdateCallback100Imp::OperationResult(INT32 aOperationResult)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message)
+{
+ CSysString s = UnicodeStringToMultiByte(message, CP_OEMCP);
+ if (g_StartupInfo.ShowMessage(s) == -1)
+ return E_ABORT;
+ return S_OK;
+}
+
diff --git a/CPP/7zip/UI/Far/UpdateCallback100.h b/CPP/7zip/UI/Far/UpdateCallback100.h
new file mode 100755
index 00000000..d66137cc
--- /dev/null
+++ b/CPP/7zip/UI/Far/UpdateCallback100.h
@@ -0,0 +1,45 @@
+// UpdateCallback.h
+
+#ifndef __UPDATECALLBACK100_H
+#define __UPDATECALLBACK100_H
+
+#include "Common/String.h"
+#include "Common/MyCom.h"
+
+#include "../Agent/IFolderArchive.h"
+
+#include "ProgressBox.h"
+
+class CUpdateCallback100Imp:
+ public IFolderArchiveUpdateCallback,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ // IProfress
+
+ STDMETHOD(SetTotal)(UINT64 aSize);
+ STDMETHOD(SetCompleted)(const UINT64 *aCompleteValue);
+
+ // IUpdateCallBack
+ STDMETHOD(CompressOperation)(const wchar_t *aName);
+ STDMETHOD(DeleteOperation)(const wchar_t *aName);
+ STDMETHOD(OperationResult)(INT32 aOperationResult);
+ STDMETHOD(UpdateErrorMessage)(const wchar_t *message);
+
+private:
+ CMyComPtr<IInFolderArchive> m_ArchiveHandler;
+ CProgressBox *m_ProgressBox;
+public:
+ void Init(IInFolderArchive *anArchiveHandler,
+ CProgressBox *aProgressBox)
+ {
+ m_ArchiveHandler = anArchiveHandler;
+ m_ProgressBox = aProgressBox;
+ }
+};
+
+
+
+#endif
diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile
new file mode 100755
index 00000000..4dbd1988
--- /dev/null
+++ b/CPP/7zip/UI/Far/makefile
@@ -0,0 +1,102 @@
+PROG = 7-ZipFar.dll
+DEF_FILE = Far.def
+LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib ole32.lib
+CFLAGS = $(CFLAGS) -I ../../../ -DWIN_LONG_PATH
+
+FAR_OBJS = \
+ $O\CLSIDConst.obj \
+ $O\ExtractEngine.obj \
+ $O\FarUtils.obj \
+ $O\Main.obj \
+ $O\OverwriteDialog.obj \
+ $O\Plugin.obj \
+ $O\PluginCommon.obj \
+ $O\PluginDelete.obj \
+ $O\PluginRead.obj \
+ $O\PluginWrite.obj \
+ $O\ProgressBox.obj \
+ $O\UpdateCallback100.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\Vector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\Error.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileName.obj \
+ $O\PropVariant.obj \
+ $O\PropVariantConversions.obj \
+ $O\Registry.obj \
+ $O\Synchronization.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\FilePathAutoRename.obj \
+ $O\FileStreams.obj \
+ $O\StreamUtils.obj \
+
+UI_COMMON_OBJS = \
+ $O\ArchiveExtractCallback.obj \
+ $O\ArchiveOpenCallback.obj \
+ $O\ArchiverInfo.obj \
+ $O\DefaultName.obj \
+ $O\EnumDirItems.obj \
+ $O\ExtractingFilePath.obj \
+ $O\OpenArchive.obj \
+ $O\PropIDUtils.obj \
+ $O\SortUtils.obj \
+ $O\UpdateAction.obj \
+ $O\UpdateCallback.obj \
+ $O\UpdatePair.obj \
+ $O\UpdateProduce.obj \
+ $O\WorkDir.obj \
+ $O\ZipRegistry.obj \
+
+AGENT_OBJS = \
+ $O\Agent.obj \
+ $O\AgentOut.obj \
+ $O\AgentProxy.obj \
+ $O\UpdateCallbackAgent.obj \
+
+C_OBJS = \
+ $O\Sort.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(FAR_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(UI_COMMON_OBJS) \
+ $(AGENT_OBJS) \
+ $(C_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(FAR_OBJS): $(*B).cpp
+ $(COMPL)
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+ $(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+ $(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+ $(COMPL)
+$(UI_COMMON_OBJS): ../Common/$(*B).cpp
+ $(COMPL)
+$(AGENT_OBJS): ../Agent/$(*B).cpp
+ $(COMPL)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
+$(C_OBJS): ../../../../C/$(*B).c
+ $(COMPL_O2)
diff --git a/CPP/7zip/UI/Far/resource.rc b/CPP/7zip/UI/Far/resource.rc
new file mode 100755
index 00000000..a5c2e2f3
--- /dev/null
+++ b/CPP/7zip/UI/Far/resource.rc
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("7-Zip Plugin for FAR Manager", "7-ZipFar")
diff --git a/CPP/7zip/UI/GUI/7zG.exe.manifest b/CPP/7zip/UI/GUI/7zG.exe.manifest
new file mode 100755
index 00000000..c6ef90e8
--- /dev/null
+++ b/CPP/7zip/UI/GUI/7zG.exe.manifest
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.7zG" type="win32"/><description>7-Zip GUI.</description><dependency> <dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly></dependency></assembly>
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp
new file mode 100755
index 00000000..f49bb078
--- /dev/null
+++ b/CPP/7zip/UI/GUI/CompressDialog.cpp
@@ -0,0 +1,1373 @@
+// CompressDialog.cpp
+
+#include "StdAfx.h"
+
+#include "resource.h"
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+#include "Windows/CommonDialog.h"
+#include "Windows/FileDir.h"
+#include "Windows/FileName.h"
+#include "Windows/ResourceString.h"
+#include "Windows/System.h"
+
+#include "../../FileManager/HelpUtils.h"
+#include "../../FileManager/SplitUtils.h"
+#include "../../FileManager/FormatUtils.h"
+
+#include "../Explorer/MyMessages.h"
+
+#include "../Common/ZipRegistry.h"
+
+#include "CompressDialog.h"
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
+#ifdef LANG
+#include "../../FileManager/LangUtils.h"
+#endif
+
+#include "../Resource/CompressDialog/resource.h"
+
+#define MY_SIZE_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
+
+#ifdef LANG
+static CIDLangPair kIDLangPairs[] =
+{
+ { IDC_STATIC_COMPRESS_ARCHIVE, 0x02000D01 },
+ { IDC_STATIC_COMPRESS_FORMAT, 0x02000D03 },
+ { IDC_STATIC_COMPRESS_LEVEL, 0x02000D0B },
+ { IDC_STATIC_COMPRESS_METHOD, 0x02000D04 },
+ { IDC_STATIC_COMPRESS_DICTIONARY, 0x02000D0C },
+ { IDC_STATIC_COMPRESS_ORDER, 0x02000D0D },
+ { IDC_STATIC_COMPRESS_MEMORY, 0x02000D0E },
+ { IDC_STATIC_COMPRESS_MEMORY_DE, 0x02000D0F },
+ { IDC_COMPRESS_SOLID, 0x02000D05 },
+ { IDC_COMPRESS_MULTI_THREAD, 0x02000D09 },
+ { IDC_STATIC_COMPRESS_VOLUME, 0x02000D40 },
+ { IDC_STATIC_COMPRESS_PARAMETERS, 0x02000D06 },
+
+ { IDC_STATIC_COMPRESS_UPDATE_MODE, 0x02000D02 },
+ { IDC_STATIC_COMPRESS_OPTIONS, 0x02000D07 },
+ { IDC_COMPRESS_SFX, 0x02000D08 },
+
+ { IDC_COMPRESS_ENCRYPTION, 0x02000D10 },
+ { IDC_STATIC_COMPRESS_PASSWORD1, 0x02000B01 },
+ { IDC_STATIC_COMPRESS_PASSWORD2, 0x02000B03 },
+ { IDC_COMPRESS_CHECK_SHOW_PASSWORD, 0x02000B02 },
+ { IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, 0x02000D11 },
+ { IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, 0x02000D0A },
+
+ { IDOK, 0x02000702 },
+ { IDCANCEL, 0x02000710 },
+ { IDHELP, 0x02000720 }
+};
+#endif
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NName;
+using namespace NDirectory;
+
+static const int kHistorySize = 8;
+
+static LPCWSTR kExeExt = L".exe";
+static LPCWSTR k7zFormat = L"7z";
+
+struct CLevelInfo
+{
+ UInt32 ResourceID;
+ UInt32 LangID;
+};
+
+enum ELevel
+{
+ kStore = 0,
+ kFastest = 1,
+ kFast = 3,
+ kNormal = 5,
+ kMaximum = 7,
+ kUltra = 9
+};
+
+static const CLevelInfo g_Levels[] =
+{
+ { IDS_METHOD_STORE, 0x02000D81 },
+ { IDS_METHOD_FASTEST, 0x02000D85 },
+ { 0, 0 },
+ { IDS_METHOD_FAST, 0x02000D84 },
+ { 0, 0 },
+ { IDS_METHOD_NORMAL, 0x02000D82 },
+ { 0, 0 },
+ { IDS_METHOD_MAXIMUM, 0x02000D83 },
+ { 0, 0 },
+ { IDS_METHOD_ULTRA, 0x02000D86 }
+};
+
+enum EMethodID
+{
+ kCopy,
+ kLZMA,
+ kPPMd,
+ kBZip2,
+ kDeflate,
+ kDeflate64
+};
+
+static const LPCWSTR kMethodsNames[] =
+{
+ L"Copy",
+ L"LZMA",
+ L"PPMd",
+ L"BZip2",
+ L"Deflate",
+ L"Deflate64"
+};
+
+static const EMethodID g_7zMethods[] =
+{
+ kLZMA,
+ kPPMd,
+ kBZip2
+};
+
+static const EMethodID g_7zSfxMethods[] =
+{
+ kCopy,
+ kLZMA,
+ kPPMd
+};
+
+static EMethodID g_ZipMethods[] =
+{
+ kDeflate,
+ kDeflate64,
+ kBZip2
+};
+
+static EMethodID g_GZipMethods[] =
+{
+ kDeflate
+};
+
+static EMethodID g_BZip2Methods[] =
+{
+ kBZip2
+};
+
+struct CFormatInfo
+{
+ LPCWSTR Name;
+ UInt32 LevelsMask;
+ const EMethodID *MathodIDs;
+ int NumMethods;
+ bool Filter;
+ bool Solid;
+ bool MultiThread;
+ bool SFX;
+ bool Encrypt;
+ bool EncryptFileNames;
+};
+
+static const CFormatInfo g_Formats[] =
+{
+ {
+ L"",
+ (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
+ 0, 0,
+ false, false, false, false, false, false
+ },
+ {
+ k7zFormat,
+ (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
+ g_7zMethods, MY_SIZE_OF_ARRAY(g_7zMethods),
+ true, true, true, true, true, true
+ },
+ {
+ L"Zip",
+ (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
+ g_ZipMethods, MY_SIZE_OF_ARRAY(g_ZipMethods) ,
+ false, false, true, false, true, false
+ },
+ {
+ L"GZip",
+ (1 << 5) | (1 << 7) | (1 << 9),
+ g_GZipMethods, MY_SIZE_OF_ARRAY(g_GZipMethods),
+ false, false, false, false, false, false
+ },
+ {
+ L"BZip2",
+ (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
+ g_BZip2Methods,
+ MY_SIZE_OF_ARRAY(g_BZip2Methods),
+ false, false, true, false, false
+ },
+ {
+ L"Tar",
+ (1 << 0),
+ 0, 0,
+ false, false, false, false, false, false
+ }
+};
+
+static bool IsMethodSupportedBySfx(int methodID)
+{
+ for (int i = 0; i < MY_SIZE_OF_ARRAY(g_7zSfxMethods); i++)
+ if (methodID == g_7zSfxMethods[i])
+ return true;
+ return false;
+};
+
+#ifndef _WIN64
+typedef BOOL (WINAPI *GlobalMemoryStatusExP)(LPMEMORYSTATUSEX lpBuffer);
+#endif
+
+static UInt64 GetPhysicalRamSize()
+{
+ MEMORYSTATUSEX stat;
+ stat.dwLength = sizeof(stat);
+ // return (128 << 20);
+ #ifdef _WIN64
+ if (!::GlobalMemoryStatusEx(&stat))
+ return 0;
+ return stat.ullTotalPhys;
+ #else
+ GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP)
+ ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")),
+ "GlobalMemoryStatusEx");
+ if (globalMemoryStatusEx != 0)
+ if (globalMemoryStatusEx(&stat))
+ return stat.ullTotalPhys;
+ {
+ MEMORYSTATUS stat;
+ stat.dwLength = sizeof(stat);
+ GlobalMemoryStatus(&stat);
+ return stat.dwTotalPhys;
+ }
+ #endif
+}
+
+static UInt64 GetMaxRamSizeForProgram()
+{
+ UInt64 physSize = GetPhysicalRamSize();
+ const UInt64 kMinSysSize = (1 << 24);
+ if (physSize <= kMinSysSize)
+ physSize = 0;
+ else
+ physSize -= kMinSysSize;
+ const UInt64 kMinUseSize = (1 << 25);
+ if (physSize < kMinUseSize)
+ physSize = kMinUseSize;
+ return physSize;
+}
+
+bool CCompressDialog::OnInit()
+{
+ #ifdef LANG
+ LangSetWindowText(HWND(*this), 0x02000D00);
+ LangSetDlgItemsText(HWND(*this), kIDLangPairs, MY_SIZE_OF_ARRAY(kIDLangPairs) );
+ #endif
+ _password1Control.Attach(GetItem(IDC_COMPRESS_EDIT_PASSWORD1));
+ _password2Control.Attach(GetItem(IDC_COMPRESS_EDIT_PASSWORD2));
+ _password1Control.SetText(Info.Password);
+ _password2Control.SetText(Info.Password);
+ _encryptionMethod.Attach(GetItem(IDC_COMPRESS_COMBO_ENCRYPTION_METHOD));
+
+ m_ArchivePath.Attach(GetItem(IDC_COMPRESS_COMBO_ARCHIVE));
+ m_Format.Attach(GetItem(IDC_COMPRESS_COMBO_FORMAT));
+ m_Level.Attach(GetItem(IDC_COMPRESS_COMBO_LEVEL));
+ m_Method.Attach(GetItem(IDC_COMPRESS_COMBO_METHOD));
+ m_Dictionary.Attach(GetItem(IDC_COMPRESS_COMBO_DICTIONARY));
+ m_Order.Attach(GetItem(IDC_COMPRESS_COMBO_ORDER));
+
+ m_UpdateMode.Attach(GetItem(IDC_COMPRESS_COMBO_UPDATE_MODE));
+ m_Volume.Attach(GetItem(IDC_COMPRESS_COMBO_VOLUME));
+ m_Params.Attach(GetItem(IDC_COMPRESS_EDIT_PARAMETERS));
+
+ AddVolumeItems(m_Volume);
+
+ ReadCompressionInfo(m_RegistryInfo);
+ CheckButton(IDC_COMPRESS_CHECK_SHOW_PASSWORD, m_RegistryInfo.ShowPassword);
+ CheckButton(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders);
+
+ UpdatePasswordControl();
+
+ Info.ArchiverInfoIndex = 0;
+ int i;
+ for(i = 0; i < m_ArchiverInfoList.Size(); i++)
+ {
+ const CArchiverInfo &ai = m_ArchiverInfoList[i];
+ m_Format.AddString(ai.Name);
+ if (ai.Name.CompareNoCase(m_RegistryInfo.ArchiveType) == 0)
+ Info.ArchiverInfoIndex = i;
+ }
+ m_Format.SetCurSel(Info.ArchiverInfoIndex);
+
+ SetArchiveName(Info.ArchiveName);
+ SetLevel();
+ SetParams();
+
+ for(i = 0; i < m_RegistryInfo.HistoryArchives.Size() && i < kHistorySize; i++)
+ m_ArchivePath.AddString(m_RegistryInfo.HistoryArchives[i]);
+
+ m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_ADD, 0x02000DA1));
+ m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_UPDATE, 0x02000DA2));
+ m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_FRESH, 0x02000DA3));
+ m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE, 0x02000DA4));
+
+ m_UpdateMode.SetCurSel(0);
+
+ Info.Solid = m_RegistryInfo.Solid;
+ Info.MultiThread = m_RegistryInfo.MultiThread;
+
+ CheckButton(IDC_COMPRESS_SOLID, Info.Solid);
+ CheckButton(IDC_COMPRESS_MULTI_THREAD, Info.MultiThread);
+ CheckButton(IDC_COMPRESS_SFX, Info.SFXMode);
+
+ CheckControlsEnable();
+
+ OnButtonSFX();
+
+ SetEncryptionMethod();
+ return CModalDialog::OnInit();
+}
+
+namespace NCompressDialog
+{
+ bool CInfo::GetFullPathName(UString &result) const
+ {
+ NDirectory::MySetCurrentDirectory(CurrentDirPrefix);
+ return MyGetFullPathName(ArchiveName, result);
+ }
+}
+
+void CCompressDialog::UpdatePasswordControl()
+{
+ bool showPassword = IsShowPasswordChecked();
+ TCHAR c = showPassword ? 0: TEXT('*');
+ _password1Control.SetPasswordChar(c);
+ _password2Control.SetPasswordChar(c);
+ UString password;
+ _password1Control.GetText(password);
+ _password1Control.SetText(password);
+ _password2Control.GetText(password);
+ _password2Control.SetText(password);
+
+ int cmdShow = showPassword ? SW_HIDE : SW_SHOW;
+ ShowItem(IDC_STATIC_COMPRESS_PASSWORD2, cmdShow);
+ _password2Control.Show(cmdShow);
+}
+
+bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
+{
+ switch(buttonID)
+ {
+ case IDC_COMPRESS_BUTTON_SET_ARCHIVE:
+ {
+ OnButtonSetArchive();
+ return true;
+ }
+ case IDC_COMPRESS_SFX:
+ {
+ OnButtonSFX();
+ return true;
+ }
+ case IDC_COMPRESS_CHECK_SHOW_PASSWORD:
+ {
+ UpdatePasswordControl();
+ return true;
+ }
+ case IDC_COMPRESS_MULTI_THREAD:
+ {
+ SetMemoryUsage();
+ return true;
+ }
+ }
+ return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
+}
+
+static bool IsMultiProcessor()
+{
+ return NSystem::GetNumberOfProcessors() > 1;
+}
+
+void CCompressDialog::CheckSFXControlsEnable()
+{
+ const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
+ bool enable = fi.SFX;
+ if (enable)
+ {
+ int methodID = GetMethodID();
+ enable = (methodID == -1 || IsMethodSupportedBySfx(methodID));
+ }
+ if (!enable)
+ CheckButton(IDC_COMPRESS_SFX, false);
+ EnableItem(IDC_COMPRESS_SFX, enable);
+}
+
+void CCompressDialog::CheckVolumeEnable()
+{
+ bool isSFX = IsSFX();
+ m_Volume.Enable(!isSFX);
+ if (isSFX)
+ m_Volume.SetText(TEXT(""));
+}
+
+void CCompressDialog::CheckControlsEnable()
+{
+ const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
+ Info.SolidIsAllowed = fi.Solid;
+ bool multiThreadEnable = fi.MultiThread & IsMultiProcessor();
+ Info.MultiThreadIsAllowed = multiThreadEnable;
+ Info.EncryptHeadersIsAllowed = fi.EncryptFileNames;
+
+ EnableItem(IDC_COMPRESS_SOLID, fi.Solid);
+ EnableItem(IDC_COMPRESS_MULTI_THREAD, multiThreadEnable);
+ CheckSFXControlsEnable();
+ CheckVolumeEnable();
+
+ EnableItem(IDC_COMPRESS_ENCRYPTION, fi.Encrypt);
+
+ EnableItem(IDC_STATIC_COMPRESS_PASSWORD1, fi.Encrypt);
+ EnableItem(IDC_STATIC_COMPRESS_PASSWORD2, fi.Encrypt);
+ EnableItem(IDC_COMPRESS_EDIT_PASSWORD1, fi.Encrypt);
+ EnableItem(IDC_COMPRESS_EDIT_PASSWORD2, fi.Encrypt);
+ EnableItem(IDC_COMPRESS_CHECK_SHOW_PASSWORD, fi.Encrypt);
+
+ EnableItem(IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt);
+ EnableItem(IDC_COMPRESS_COMBO_ENCRYPTION_METHOD, fi.Encrypt);
+ EnableItem(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, fi.EncryptFileNames);
+}
+
+bool CCompressDialog::IsSFX()
+{
+ CWindow sfxButton = GetItem(IDC_COMPRESS_SFX);
+ return sfxButton.IsEnabled() && IsButtonCheckedBool(IDC_COMPRESS_SFX);
+}
+
+void CCompressDialog::OnButtonSFX()
+{
+ SetMethod();
+
+ UString fileName;
+ m_ArchivePath.GetText(fileName);
+ int dotPos = fileName.ReverseFind(L'.');
+ int slashPos = fileName.ReverseFind(L'\\');
+ if (dotPos < 0 || dotPos <= slashPos)
+ dotPos = -1;
+ bool isSFX = IsSFX();
+ if (isSFX)
+ {
+ if (dotPos >= 0)
+ fileName = fileName.Left(dotPos);
+ fileName += kExeExt;
+ m_ArchivePath.SetText(fileName);
+ }
+ else
+ {
+ if (dotPos >= 0)
+ {
+ UString ext = fileName.Mid(dotPos);
+ if (ext.CompareNoCase(kExeExt) == 0)
+ {
+ fileName = fileName.Left(dotPos);
+ m_ArchivePath.SetText(fileName);
+ }
+ }
+ SetArchiveName2(false); // it's for OnInit
+ }
+
+ CheckVolumeEnable();
+}
+
+void CCompressDialog::OnButtonSetArchive()
+{
+ UString fileName;
+ m_ArchivePath.GetText(fileName);
+ fileName.Trim();
+ Info.ArchiveName = fileName;
+ UString fullFileName;
+ if (!Info.GetFullPathName(fullFileName))
+ {
+ fullFileName = Info.ArchiveName;
+ return;
+ }
+ UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE, 0x02000D90);
+ UString s = LangString(IDS_OPEN_TYPE_ALL_FILES, 0x02000DB1);
+ s += L" (*.*)";
+ UString resPath;
+ if (!MyGetOpenFileName(HWND(*this), title, fullFileName, s, resPath))
+ return;
+ m_ArchivePath.SetText(resPath);
+}
+
+// in ExtractDialog.cpp
+extern void AddUniqueString(UStringVector &strings, const UString &srcString);
+
+static bool IsAsciiString(const UString &s)
+{
+ for (int i = 0; i < s.Length(); i++)
+ {
+ wchar_t c = s[i];
+ if (c < 0x20 || c > 0x7F)
+ return false;
+ }
+ return true;
+}
+
+void CCompressDialog::OnOK()
+{
+ _password1Control.GetText(Info.Password);
+ if (IsZipFormat())
+ {
+ if (!IsAsciiString(Info.Password))
+ {
+ MyMessageBoxResource(*this, IDS_PASSWORD_USE_ASCII, 0x02000B11);
+ return;
+ }
+ UString method = GetEncryptionMethodSpec();
+ method.MakeUpper();
+ if (method.Find(L"AES") == 0)
+ {
+ if (Info.Password.Length() > 99)
+ {
+ MyMessageBoxResource(*this, IDS_PASSWORD_IS_TOO_LONG, 0x02000B12);
+ return;
+ }
+ }
+ }
+ if (!IsShowPasswordChecked())
+ {
+ UString password2;
+ _password2Control.GetText(password2);
+ if (password2 != Info.Password)
+ {
+ MyMessageBoxResource(*this, IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH, 0x02000B10);
+ return;
+ }
+ }
+
+ SaveOptionsInMem();
+ UString s;
+ m_ArchivePath.GetText(s);
+ s.Trim();
+ m_RegistryInfo.HistoryArchives.Clear();
+ AddUniqueString(m_RegistryInfo.HistoryArchives, s);
+ Info.ArchiveName = s;
+ Info.UpdateMode = NCompressDialog::NUpdateMode::EEnum(m_UpdateMode.GetCurSel());
+
+ Info.Level = GetLevelSpec();
+ Info.Dictionary = GetDictionarySpec();
+ Info.Order = GetOrderSpec();
+ Info.OrderMode = GetOrderMode();
+ Info.Method = GetMethodSpec();
+ Info.EncryptionMethod = GetEncryptionMethodSpec();
+
+ Info.ArchiverInfoIndex = m_Format.GetCurSel();
+
+ Info.SFXMode = IsSFX();
+ m_RegistryInfo.Solid = Info.Solid = IsButtonCheckedBool(IDC_COMPRESS_SOLID);
+ m_RegistryInfo.MultiThread = Info.MultiThread = IsMultiThread();
+ m_RegistryInfo.EncryptHeaders = Info.EncryptHeaders = IsButtonCheckedBool(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES);
+
+ m_Params.GetText(Info.Options);
+ UString volumeString;
+ m_Volume.GetText(volumeString);
+ volumeString.Trim();
+ Info.VolumeSizes.Clear();
+ if (!volumeString.IsEmpty())
+ {
+ if (!ParseVolumeSizes(volumeString, Info.VolumeSizes))
+ {
+ MyMessageBoxResource(*this, IDS_COMPRESS_INCORRECT_VOLUME_SIZE, 0x02000D41);
+ return;
+ }
+ if (!Info.VolumeSizes.IsEmpty())
+ {
+ const UInt64 volumeSize = Info.VolumeSizes.Back();
+ if (volumeSize < (100 << 10))
+ {
+ wchar_t s[32];
+ ConvertUInt64ToString(volumeSize, s);
+ if (::MessageBoxW(*this, MyFormatNew(IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE, 0x02000D42, s),
+ L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION | MB_TASKMODAL) != IDYES)
+ return;
+ }
+ }
+ }
+
+ for(int i = 0; i < m_ArchivePath.GetCount(); i++)
+ {
+ UString sTemp;
+ m_ArchivePath.GetLBText(i, sTemp);
+ sTemp.Trim();
+ AddUniqueString(m_RegistryInfo.HistoryArchives, sTemp);
+ }
+ if (m_RegistryInfo.HistoryArchives.Size() > kHistorySize)
+ m_RegistryInfo.HistoryArchives.DeleteBack();
+
+ ////////////////////
+ // Method
+
+ m_RegistryInfo.Level = Info.Level;
+ m_RegistryInfo.ArchiveType = m_ArchiverInfoList[Info.ArchiverInfoIndex].Name;
+
+ m_RegistryInfo.ShowPassword = IsShowPasswordChecked();
+
+ SaveCompressionInfo(m_RegistryInfo);
+
+ CModalDialog::OnOK();
+}
+
+static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/add.htm";
+
+void CCompressDialog::OnHelp()
+{
+ ShowHelpWindow(NULL, kHelpTopic);
+}
+
+bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
+{
+ if (code == CBN_SELCHANGE)
+ {
+ switch(itemID)
+ {
+ case IDC_COMPRESS_COMBO_FORMAT:
+ {
+ OnChangeFormat();
+ return true;
+ }
+ case IDC_COMPRESS_COMBO_LEVEL:
+ {
+ const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
+ int index = FindRegistryFormatAlways(ai.Name);
+ NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
+ fo.ResetForLevelChange();
+ SetMethod();
+ CheckSFXNameChange();
+ return true;
+ }
+ case IDC_COMPRESS_COMBO_METHOD:
+ {
+ SetDictionary();
+ SetOrder();
+ CheckSFXNameChange();
+ return true;
+ }
+ case IDC_COMPRESS_COMBO_DICTIONARY:
+ case IDC_COMPRESS_COMBO_ORDER:
+ {
+ SetMemoryUsage();
+ return true;
+ }
+ }
+ }
+ return CModalDialog::OnCommand(code, itemID, lParam);
+}
+
+void CCompressDialog::CheckSFXNameChange()
+{
+ bool isSFX = IsSFX();
+ CheckSFXControlsEnable();
+ if (isSFX != IsSFX())
+ SetArchiveName2(isSFX);
+}
+
+void CCompressDialog::SetArchiveName2(bool prevWasSFX)
+{
+ UString fileName;
+ m_ArchivePath.GetText(fileName);
+ const CArchiverInfo &prevArchiverInfo = m_ArchiverInfoList[m_PrevFormat];
+ if (prevArchiverInfo.KeepName || Info.KeepName)
+ {
+ UString prevExtension = prevArchiverInfo.GetMainExtension();
+ if (prevWasSFX)
+ prevExtension = kExeExt;
+ else
+ prevExtension = UString('.') + prevExtension;
+ const int prevExtensionLen = prevExtension.Length();
+ if (fileName.Length() >= prevExtensionLen)
+ if (fileName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0)
+ fileName = fileName.Left(fileName.Length() - prevExtensionLen);
+ }
+ SetArchiveName(fileName);
+}
+
+void CCompressDialog::OnChangeFormat()
+{
+ bool isSFX = IsSFX();
+ SaveOptionsInMem();
+ SetLevel();
+ SetParams();
+ CheckControlsEnable();
+ SetArchiveName2(isSFX);
+ SetEncryptionMethod();
+}
+
+// if type.KeepName then use OriginalFileName
+// else if !KeepName remove extension
+// add new extension
+
+void CCompressDialog::SetArchiveName(const UString &name)
+{
+ UString fileName = name;
+ Info.ArchiverInfoIndex = m_Format.GetCurSel();
+ const CArchiverInfo &ai = m_ArchiverInfoList[Info.ArchiverInfoIndex];
+ m_PrevFormat = Info.ArchiverInfoIndex;
+ if (ai.KeepName)
+ {
+ fileName = OriginalFileName;
+ }
+ else
+ {
+ if (!Info.KeepName)
+ {
+ int dotPos = fileName.ReverseFind('.');
+ int slashPos = MyMax(fileName.ReverseFind('\\'), fileName.ReverseFind('/'));
+ if (dotPos >= 0 && dotPos > slashPos + 1)
+ fileName = fileName.Left(dotPos);
+ }
+ }
+
+ if (IsSFX())
+ fileName += kExeExt;
+ else
+ {
+ fileName += L'.';
+ fileName += ai.GetMainExtension();
+ }
+ m_ArchivePath.SetText(fileName);
+}
+
+int CCompressDialog::FindRegistryFormat(const UString &name)
+{
+ for (int i = 0; i < m_RegistryInfo.FormatOptionsVector.Size(); i++)
+ {
+ const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[i];
+ if (GetUnicodeString(fo.FormatID) == name)
+ return i;
+ }
+ return -1;
+}
+
+int CCompressDialog::FindRegistryFormatAlways(const UString &name)
+{
+ int index = FindRegistryFormat(name);
+ if (index < 0)
+ {
+ NCompression::CFormatOptions fo;
+ fo.FormatID = GetSystemString(name);
+ index = m_RegistryInfo.FormatOptionsVector.Add(fo);
+ }
+ return index;
+}
+
+int CCompressDialog::GetStaticFormatIndex()
+{
+ int formatIndex = m_Format.GetCurSel();
+ const CArchiverInfo &ai = m_ArchiverInfoList[formatIndex];
+ for (int i = 0; i < MY_SIZE_OF_ARRAY(g_Formats); i++)
+ if (ai.Name.CompareNoCase(g_Formats[i].Name) == 0)
+ return i;
+ return 0; // -1;
+}
+
+void CCompressDialog::SetNearestSelectComboBox(
+ NControl::CComboBox &comboBox, UInt32 value)
+{
+ for (int i = comboBox.GetCount() - 1; i >= 0; i--)
+ if ((UInt32)comboBox.GetItemData(i) <= value)
+ {
+ comboBox.SetCurSel(i);
+ return;
+ }
+ if (comboBox.GetCount() > 0)
+ comboBox.SetCurSel(0);
+}
+
+void CCompressDialog::SetLevel()
+{
+ m_Level.ResetContent();
+ const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
+ const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
+ int index = FindRegistryFormat(ai.Name);
+ UInt32 level = kNormal;
+ if (index >= 0)
+ {
+ const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
+ if (fo.Level <= kUltra)
+ level = fo.Level;
+ else
+ level = kUltra;
+ }
+ int i;
+ for (i = 0; i <= kUltra; i++)
+ {
+ if ((fi.LevelsMask & (1 << i)) != 0)
+ {
+ const CLevelInfo &levelInfo = g_Levels[i];
+ int index = (int)m_Level.AddString(LangString(levelInfo.ResourceID, levelInfo.LangID));
+ m_Level.SetItemData(index, i);
+ }
+ }
+ SetNearestSelectComboBox(m_Level, level);
+ SetMethod();
+}
+
+int CCompressDialog::GetLevel()
+{
+ if (m_Level.GetCount() <= 0)
+ return -1;
+ return (int)m_Level.GetItemData(m_Level.GetCurSel());
+}
+
+int CCompressDialog::GetLevelSpec()
+{
+ if (m_Level.GetCount() <= 1)
+ return -1;
+ return GetLevel();
+}
+
+int CCompressDialog::GetLevel2()
+{
+ int level = GetLevel();
+ if (level < 0)
+ level = 5;
+ return level;
+}
+
+bool CCompressDialog::IsMultiThread()
+{
+ /*
+ const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
+ bool multiThreadEnable = fi.MultiThread & IsMultiProcessor();
+ if (!multiThreadEnable)
+ return false;
+ */
+ return IsButtonCheckedBool(IDC_COMPRESS_MULTI_THREAD);
+}
+
+void CCompressDialog::SetMethod()
+{
+ m_Method.ResetContent();
+ if (GetLevel() <= 0)
+ {
+ SetDictionary();
+ SetOrder();
+ return;
+ }
+ const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
+ const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
+ int index = FindRegistryFormat(ai.Name);
+ UString defaultMethod;
+ if (index >= 0)
+ {
+ const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
+ defaultMethod = fo.Method;
+ }
+ bool isSfx = IsSFX();
+ for(int m = 0; m < fi.NumMethods; m++)
+ {
+ EMethodID methodID = fi.MathodIDs[m];
+ if (isSfx)
+ if (!IsMethodSupportedBySfx(methodID))
+ continue;
+ const LPCWSTR method = kMethodsNames[methodID];
+ int itemIndex = (int)m_Method.AddString(GetSystemString(method));
+ if (defaultMethod.CompareNoCase(method) == 0 || m == 0)
+ m_Method.SetCurSel(itemIndex);
+ }
+ SetDictionary();
+ SetOrder();
+}
+
+bool CCompressDialog::IsZipFormat()
+{
+ const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
+ return (ai.Name.CompareNoCase(L"zip") == 0);
+}
+
+void CCompressDialog::SetEncryptionMethod()
+{
+ _encryptionMethod.ResetContent();
+ const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
+ if (ai.Name.CompareNoCase(L"7z") == 0)
+ {
+ _encryptionMethod.AddString(TEXT("AES-256"));
+ _encryptionMethod.SetCurSel(0);
+ }
+ else if (ai.Name.CompareNoCase(L"zip") == 0)
+ {
+ int index = FindRegistryFormat(ai.Name);
+ UString encryptionMethod;
+ if (index >= 0)
+ {
+ const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
+ encryptionMethod = fo.EncryptionMethod;
+ }
+ _encryptionMethod.AddString(TEXT("ZipCrypto"));
+ _encryptionMethod.AddString(TEXT("AES-256"));
+ _encryptionMethod.SetCurSel(encryptionMethod.Find(L"AES") == 0 ? 1 : 0);
+ }
+}
+
+int CCompressDialog::GetMethodID()
+{
+ UString methodName;
+ m_Method.GetText(methodName);
+ for (int i = 0; i < MY_SIZE_OF_ARRAY(kMethodsNames); i++)
+ if (methodName.CompareNoCase(kMethodsNames[i]) == 0)
+ return i;
+ return -1;
+}
+
+UString CCompressDialog::GetMethodSpec()
+{
+ if (m_Method.GetCount() <= 1)
+ return UString();
+ UString result;
+ m_Method.GetText(result);
+ return result;
+}
+
+UString CCompressDialog::GetEncryptionMethodSpec()
+{
+ if (m_Method.GetCount() <= 1)
+ return UString();
+ if (_encryptionMethod.GetCurSel() <= 0)
+ return UString();
+ UString result;
+ _encryptionMethod.GetText(result);
+ result.Replace(L"-", L"");
+ return result;
+}
+
+int CCompressDialog::AddDictionarySize(UInt32 size, bool kilo, bool maga)
+{
+ UInt32 sizePrint = size;
+ if (kilo)
+ sizePrint >>= 10;
+ else if (maga)
+ sizePrint >>= 20;
+ TCHAR s[40];
+ ConvertUInt64ToString(sizePrint, s);
+ if (kilo)
+ lstrcat(s, TEXT(" K"));
+ else if (maga)
+ lstrcat(s, TEXT(" M"));
+ else
+ lstrcat(s, TEXT(" "));
+ lstrcat(s, TEXT("B"));
+ int index = (int)m_Dictionary.AddString(s);
+ m_Dictionary.SetItemData(index, size);
+ return index;
+}
+
+int CCompressDialog::AddDictionarySize(UInt32 size)
+{
+ if (size > 0)
+ {
+ if ((size & 0xFFFFF) == 0)
+ return AddDictionarySize(size, false, true);
+ if ((size & 0x3FF) == 0)
+ return AddDictionarySize(size, true, false);
+ }
+ return AddDictionarySize(size, false, false);
+}
+
+void CCompressDialog::SetDictionary()
+{
+ m_Dictionary.ResetContent();
+ const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
+ int index = FindRegistryFormat(ai.Name);
+ UInt32 defaultDictionary = UInt32(-1);
+ if (index >= 0)
+ {
+ const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
+ if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)
+ defaultDictionary = fo.Dictionary;
+ }
+ int methodID = GetMethodID();
+ int level = GetLevel2();
+ if (methodID < 0)
+ {
+ SetMemoryUsage();
+ return;
+ }
+ const UInt64 maxRamSize = GetMaxRamSizeForProgram();
+ switch (methodID)
+ {
+ case kLZMA:
+ {
+ static const UInt32 kMinDicSize = (1 << 16);
+ if (defaultDictionary == UInt32(-1))
+ {
+ if (level >= 9)
+ defaultDictionary = (1 << 26);
+ else if (level >= 7)
+ defaultDictionary = (1 << 24);
+ else if (level >= 5)
+ defaultDictionary = (1 << 22);
+ else if (level >= 3)
+ defaultDictionary = (1 << 20);
+ else
+ defaultDictionary = (kMinDicSize);
+ }
+ int i;
+ AddDictionarySize(kMinDicSize);
+ m_Dictionary.SetCurSel(0);
+ for (i = 20; i <= 30; i++)
+ for (int j = 0; j < 2; j++)
+ {
+ if (i == 20 && j > 0)
+ continue;
+ UInt32 dictionary = (1 << i) + (j << (i - 1));
+ if (dictionary >
+ #ifdef _WIN64
+ (1 << 30)
+ #else
+ (1 << 27)
+ #endif
+ )
+ continue;
+ AddDictionarySize(dictionary);
+ UInt64 decomprSize;
+ UInt64 requiredComprSize = GetMemoryUsage(dictionary, false, decomprSize);
+ if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize)
+ m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
+ }
+
+ // SetNearestSelectComboBox(m_Dictionary, defaultDictionary);
+ break;
+ }
+ case kPPMd:
+ {
+ if (defaultDictionary == UInt32(-1))
+ {
+ if (level >= 9)
+ defaultDictionary = (192 << 20);
+ else if (level >= 7)
+ defaultDictionary = (64 << 20);
+ else if (level >= 5)
+ defaultDictionary = (16 << 20);
+ else
+ defaultDictionary = (4 << 20);
+ }
+ int i;
+ for (i = 20; i < 31; i++)
+ for (int j = 0; j < 2; j++)
+ {
+ if (i == 20 && j > 0)
+ continue;
+ UInt32 dictionary = (1 << i) + (j << (i - 1));
+ if (dictionary >= (1 << 31))
+ continue;
+ AddDictionarySize(dictionary);
+ UInt64 decomprSize;
+ UInt64 requiredComprSize = GetMemoryUsage(dictionary, false, decomprSize);
+ if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0)
+ m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
+ }
+ SetNearestSelectComboBox(m_Dictionary, defaultDictionary);
+ break;
+ }
+ case kDeflate:
+ {
+ AddDictionarySize(32 << 10);
+ m_Dictionary.SetCurSel(0);
+ break;
+ }
+ case kDeflate64:
+ {
+ AddDictionarySize(64 << 10);
+ m_Dictionary.SetCurSel(0);
+ break;
+ }
+ case kBZip2:
+ {
+ UInt32 defaultDictionary;
+ if (level >= 5)
+ defaultDictionary = (900 << 10);
+ else if (level >= 3)
+ defaultDictionary = (500 << 10);
+ else
+ defaultDictionary = (100 << 10);
+ for (int i = 1; i <= 9; i++)
+ {
+ UInt32 dictionary = (i * 100) << 10;
+ AddDictionarySize(dictionary);
+ if (dictionary <= defaultDictionary || m_Dictionary.GetCount() == 0)
+ m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
+ }
+ break;
+ }
+ }
+ SetMemoryUsage();
+}
+
+UInt32 CCompressDialog::GetDictionary()
+{
+ if (m_Dictionary.GetCount() <= 0)
+ return (UInt32)-1;
+ return (UInt32)m_Dictionary.GetItemData(m_Dictionary.GetCurSel());
+}
+
+UInt32 CCompressDialog::GetDictionarySpec()
+{
+ if (m_Dictionary.GetCount() <= 1)
+ return (UInt32)-1;
+ return GetDictionary();
+}
+
+int CCompressDialog::AddOrder(UInt32 size)
+{
+ TCHAR s[40];
+ ConvertUInt64ToString(size, s);
+ int index = (int)m_Order.AddString(s);
+ m_Order.SetItemData(index, size);
+ return index;
+}
+
+void CCompressDialog::SetOrder()
+{
+ m_Order.ResetContent();
+ const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
+ int index = FindRegistryFormat(ai.Name);
+ UInt32 defaultOrder = UInt32(-1);
+ if (index >= 0)
+ {
+ const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
+ if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)
+ defaultOrder = fo.Order;
+ }
+ int methodID = GetMethodID();
+ int level = GetLevel2();
+ if (methodID < 0)
+ {
+ SetMemoryUsage();
+ return;
+ }
+ switch (methodID)
+ {
+ case kLZMA:
+ {
+ if (defaultOrder == UInt32(-1))
+ defaultOrder = (level >= 7) ? 64 : 32;
+ for (int i = 3; i <= 8; i++)
+ for (int j = 0; j < 2; j++)
+ {
+ UInt32 order = (1 << i) + (j << (i - 1));
+ if (order <= 256)
+ AddOrder(order);
+ }
+ AddOrder(273);
+ SetNearestSelectComboBox(m_Order, defaultOrder);
+ break;
+ }
+ case kPPMd:
+ {
+ if (defaultOrder == UInt32(-1))
+ {
+ if (level >= 9)
+ defaultOrder = 32;
+ else if (level >= 7)
+ defaultOrder = 16;
+ else if (level >= 5)
+ defaultOrder = 6;
+ else
+ defaultOrder = 4;
+ }
+ int i;
+ AddOrder(2);
+ AddOrder(3);
+ for (i = 2; i < 8; i++)
+ for (int j = 0; j < 4; j++)
+ {
+ UInt32 order = (1 << i) + (j << (i - 2));
+ if (order < 32)
+ AddOrder(order);
+ }
+ AddOrder(32);
+ SetNearestSelectComboBox(m_Order, defaultOrder);
+ break;
+ }
+ case kDeflate:
+ case kDeflate64:
+ {
+ if (defaultOrder == UInt32(-1))
+ {
+ if (level >= 9)
+ defaultOrder = 128;
+ else if (level >= 7)
+ defaultOrder = 64;
+ else
+ defaultOrder = 32;
+ }
+ int i;
+ for (i = 3; i <= 8; i++)
+ for (int j = 0; j < 2; j++)
+ {
+ UInt32 order = (1 << i) + (j << (i - 1));
+ if (order <= 256)
+ AddOrder(order);
+ }
+ AddOrder(methodID == kDeflate64 ? 257 : 258);
+ SetNearestSelectComboBox(m_Order, defaultOrder);
+ break;
+ }
+ case kBZip2:
+ {
+ break;
+ }
+ }
+ SetMemoryUsage();
+}
+
+bool CCompressDialog::GetOrderMode()
+{
+ switch (GetMethodID())
+ {
+ case kPPMd:
+ return true;
+ }
+ return false;
+}
+
+UInt32 CCompressDialog::GetOrder()
+{
+ if (m_Order.GetCount() <= 0)
+ return (UInt32)-1;
+ return (UInt32)m_Order.GetItemData(m_Order.GetCurSel());
+}
+
+UInt32 CCompressDialog::GetOrderSpec()
+{
+ if (m_Order.GetCount() <= 1)
+ return (UInt32)-1;
+ return GetOrder();
+}
+
+UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, bool isMultiThread, UInt64 &decompressMemory)
+{
+ decompressMemory = UInt64(Int64(-1));
+ int level = GetLevel2();
+ if (level == 0)
+ {
+ decompressMemory = (1 << 20);
+ return decompressMemory;
+ }
+ UInt64 size = 0;
+
+ const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
+ if (fi.Filter && level >= 9)
+ size += (12 << 20) * 2 + (5 << 20);
+ switch (GetMethodID())
+ {
+ case kLZMA:
+ {
+ UInt32 hs = dictionary - 1;
+ hs |= (hs >> 1);
+ hs |= (hs >> 2);
+ hs |= (hs >> 4);
+ hs |= (hs >> 8);
+ hs >>= 1;
+ hs |= 0xFFFF;
+ if (hs > (1 << 24))
+ hs >>= 1;
+ hs++;
+ size += hs * 4;
+ size += (UInt64)dictionary * 11 / 2;
+ if (level >= 5)
+ size += dictionary * 4;
+ size += (2 << 20);
+ if (isMultiThread && level >= 5)
+ size += (2 << 20) + (4 << 20);
+
+ decompressMemory = dictionary + (2 << 20);
+ return size;
+ }
+ case kPPMd:
+ {
+ decompressMemory = dictionary + (2 << 20);
+ return size + decompressMemory;
+ }
+ case kDeflate:
+ case kDeflate64:
+ {
+ UInt32 order = GetOrder();
+ if (order == UInt32(-1))
+ order = 32;
+ if (level >= 7)
+ size += (1 << 20);
+ size += 3 << 20;
+ decompressMemory = (2 << 20);
+ return size;
+ }
+ case kBZip2:
+ {
+ decompressMemory = (7 << 20);
+ UInt64 memForOneThread = (10 << 20);
+ if (isMultiThread)
+ memForOneThread *= NSystem::GetNumberOfProcessors();
+ return size + (10 << 20);
+ }
+ }
+ return UInt64(Int64(-1));
+}
+
+UInt64 CCompressDialog::GetMemoryUsage(UInt64 &decompressMemory)
+{
+ return GetMemoryUsage(GetDictionary(), IsMultiThread(), decompressMemory);
+}
+
+void CCompressDialog::PrintMemUsage(UINT res, UInt64 value)
+{
+ if (value == (UInt64)Int64(-1))
+ {
+ SetItemText(res, TEXT("?"));
+ return;
+ }
+ value = (value + (1 << 20) - 1) >> 20;
+ TCHAR s[40];
+ ConvertUInt64ToString(value, s);
+ lstrcat(s, TEXT(" MB"));
+ SetItemText(res, s);
+}
+
+void CCompressDialog::SetMemoryUsage()
+{
+ UInt64 decompressMem;
+ UInt64 memUsage = GetMemoryUsage(decompressMem);
+ PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_VALUE, memUsage);
+ PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_DE_VALUE, decompressMem);
+}
+
+void CCompressDialog::SetParams()
+{
+ const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
+ m_Params.SetText(TEXT(""));
+ int index = FindRegistryFormat(ai.Name);
+ if (index >= 0)
+ {
+ const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
+ m_Params.SetText(fo.Options);
+ }
+}
+
+void CCompressDialog::SaveOptionsInMem()
+{
+ const CArchiverInfo &ai = m_ArchiverInfoList[Info.ArchiverInfoIndex];
+ int index = FindRegistryFormatAlways(ai.Name);
+ m_Params.GetText(Info.Options);
+ Info.Options.Trim();
+ NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
+ fo.Options = Info.Options;
+ fo.Level = GetLevelSpec();
+ fo.Dictionary = GetDictionarySpec();
+ fo.Order = GetOrderSpec();
+ fo.Method = GetMethodSpec();
+ fo.EncryptionMethod = GetEncryptionMethodSpec();
+}
diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h
new file mode 100755
index 00000000..87cf5d79
--- /dev/null
+++ b/CPP/7zip/UI/GUI/CompressDialog.h
@@ -0,0 +1,171 @@
+// CompressDialog.h
+
+#ifndef __COMPRESSDIALOG_H
+#define __COMPRESSDIALOG_H
+
+#include "../Common/ZipRegistry.h"
+#include "../Common/ArchiverInfo.h"
+#include "../Resource/CompressDialog/resource.h"
+
+#include "Windows/Control/Dialog.h"
+#include "Windows/Control/Edit.h"
+#include "Windows/Control/ComboBox.h"
+
+namespace NCompressDialog
+{
+ namespace NUpdateMode
+ {
+ enum EEnum
+ {
+ kAdd,
+ kUpdate,
+ kFresh,
+ kSynchronize,
+ };
+ }
+ struct CInfo
+ {
+ NUpdateMode::EEnum UpdateMode;
+ bool SolidIsAllowed;
+ bool Solid;
+
+ bool MultiThreadIsAllowed;
+ bool MultiThread;
+
+ CRecordVector<UInt64> VolumeSizes;
+
+ UInt32 Level;
+ UString Method;
+ UInt32 Dictionary;
+ bool OrderMode;
+ UInt32 Order;
+ UString Options;
+
+ UString EncryptionMethod;
+
+ bool SFXMode;
+
+ UString ArchiveName; // in: Relative for ; out: abs
+ UString CurrentDirPrefix;
+ bool KeepName;
+
+ bool GetFullPathName(UString &result) const;
+
+ int ArchiverInfoIndex;
+
+ UString Password;
+ bool EncryptHeadersIsAllowed;
+ bool EncryptHeaders;
+
+ void Init()
+ {
+ Level = Dictionary = Order = UInt32(-1);
+ OrderMode = false;
+ Method.Empty();
+ Options.Empty();
+ EncryptionMethod.Empty();
+ }
+ CInfo()
+ {
+ Init();
+ }
+ };
+}
+
+class CCompressDialog: public NWindows::NControl::CModalDialog
+{
+ NWindows::NControl::CComboBox m_ArchivePath;
+ NWindows::NControl::CComboBox m_Format;
+ NWindows::NControl::CComboBox m_Level;
+ NWindows::NControl::CComboBox m_Method;
+ NWindows::NControl::CComboBox m_Dictionary;
+ NWindows::NControl::CComboBox m_Order;
+ NWindows::NControl::CComboBox m_UpdateMode;
+ NWindows::NControl::CComboBox m_Volume;
+ NWindows::NControl::CDialogChildControl m_Params;
+
+ NWindows::NControl::CEdit _password1Control;
+ NWindows::NControl::CEdit _password2Control;
+ NWindows::NControl::CComboBox _encryptionMethod;
+
+ NCompression::CInfo m_RegistryInfo;
+
+ int m_PrevFormat;
+ void SetArchiveName(const UString &name);
+ int FindRegistryFormat(const UString &name);
+ int FindRegistryFormatAlways(const UString &name);
+
+ void OnChangeFormat();
+ void CheckSFXNameChange();
+ void SetArchiveName2(bool prevWasSFX);
+
+ int GetStaticFormatIndex();
+
+ void SetNearestSelectComboBox(NWindows::NControl::CComboBox &comboBox, UInt32 value);
+
+ void SetLevel();
+ int GetLevel();
+ int GetLevelSpec();
+ int GetLevel2();
+ bool IsMultiThread();
+
+ void SetMethod();
+ int GetMethodID();
+ UString GetMethodSpec();
+ UString GetEncryptionMethodSpec();
+
+ bool IsZipFormat();
+
+ void SetEncryptionMethod();
+
+ int AddDictionarySize(UInt32 size, bool kilo, bool maga);
+ int AddDictionarySize(UInt32 size);
+
+ void SetDictionary();
+ UInt32 GetDictionary();
+ UInt32 GetDictionarySpec();
+
+ int AddOrder(UInt32 size);
+ void SetOrder();
+ bool GetOrderMode();
+ UInt32 GetOrder();
+ UInt32 GetOrderSpec();
+
+ UInt64 GetMemoryUsage(UInt32 dictionary, bool isMultiThread, UInt64 &decompressMemory);
+ UInt64 GetMemoryUsage(UInt64 &decompressMemory);
+ void PrintMemUsage(UINT res, UInt64 value);
+ void SetMemoryUsage();
+ void SetParams();
+ void SaveOptionsInMem();
+
+ void UpdatePasswordControl();
+ bool IsShowPasswordChecked() const
+ { return IsButtonChecked(IDC_COMPRESS_CHECK_SHOW_PASSWORD) == BST_CHECKED; }
+public:
+ CObjectVector<CArchiverInfo> m_ArchiverInfoList;
+
+ NCompressDialog::CInfo Info;
+ UString OriginalFileName; // for bzip2, gzip2
+
+ INT_PTR Create(HWND wndParent = 0)
+ { return CModalDialog::Create(IDD_DIALOG_COMPRESS, wndParent); }
+
+protected:
+
+ void CheckSFXControlsEnable();
+ void CheckVolumeEnable();
+ void CheckControlsEnable();
+
+ void OnButtonSetArchive();
+ bool IsSFX();
+ void OnButtonSFX();
+
+ virtual bool OnInit();
+ virtual bool OnCommand(int code, int itemID, LPARAM lParam);
+ virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
+ virtual void OnOK();
+ virtual void OnHelp();
+
+};
+
+#endif
diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp
new file mode 100755
index 00000000..55c871ad
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp
@@ -0,0 +1,371 @@
+// ExtractDialog.cpp
+
+#include "StdAfx.h"
+
+// #include <HtmlHelp.h>
+
+#include "ExtractDialog.h"
+
+#include "Common/StringConvert.h"
+#include "Windows/Shell.h"
+#include "Windows/FileName.h"
+#include "Windows/FileDir.h"
+#include "Windows/ResourceString.h"
+
+#ifndef NO_REGISTRY
+#include "../../FileManager/HelpUtils.h"
+#endif
+
+#include "../Common/ZipRegistry.h"
+
+#include "../../FileManager/LangUtils.h"
+
+#include "../Resource/Extract/resource.h"
+#include "../Resource/ExtractDialog/resource.h"
+
+// #include "Help/Context/Extract.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NName;
+
+static const int kPathModeButtons[] =
+{
+ IDC_EXTRACT_RADIO_FULL_PATHNAMES,
+ IDC_EXTRACT_RADIO_CURRENT_PATHNAMES,
+ IDC_EXTRACT_RADIO_NO_PATHNAMES
+};
+
+static const NExtract::NPathMode::EEnum kPathModeButtonsVals[] =
+{
+ NExtract::NPathMode::kFullPathnames,
+ NExtract::NPathMode::kCurrentPathnames,
+ NExtract::NPathMode::kNoPathnames
+};
+
+static const int kNumPathnamesButtons = sizeof(kPathModeButtons) / sizeof(kPathModeButtons[0]);
+
+static const int kOverwriteButtons[] =
+{
+ IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE,
+ IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT,
+ IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES,
+ IDC_EXTRACT_RADIO_AUTO_RENAME,
+ IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING,
+};
+
+static const NExtract::NOverwriteMode::EEnum kOverwriteButtonsVals[] =
+{
+ NExtract::NOverwriteMode::kAskBefore,
+ NExtract::NOverwriteMode::kWithoutPrompt,
+ NExtract::NOverwriteMode::kSkipExisting,
+ NExtract::NOverwriteMode::kAutoRename,
+ NExtract::NOverwriteMode::kAutoRenameExisting
+};
+
+static const int kNumOverwriteButtons = sizeof(kOverwriteButtons) / sizeof(kOverwriteButtons[0]);
+
+/*
+static const int kFilesButtons[] =
+{
+ IDC_EXTRACT_RADIO_SELECTED_FILES,
+ IDC_EXTRACT_RADIO_ALL_FILES
+};
+static const int kNumFilesButtons = sizeof(kFilesButtons) / sizeof(kFilesButtons[0]);
+*/
+
+#ifndef _SFX
+void CExtractDialog::GetPathMode()
+{
+ for (int i = 0; i < kNumPathnamesButtons; i++)
+ if(IsButtonCheckedBool(kPathModeButtons[i]))
+ {
+ PathMode = kPathModeButtonsVals[i];
+ return;
+ }
+ throw 1;
+}
+
+void CExtractDialog::SetPathMode()
+{
+ for (int j = 0; j < 2; j++)
+ {
+ for (int i = 0; i < kNumPathnamesButtons; i++)
+ if(PathMode == kPathModeButtonsVals[i])
+ {
+ CheckRadioButton(kPathModeButtons[0], kPathModeButtons[kNumPathnamesButtons - 1],
+ kPathModeButtons[i]);
+ return;
+ }
+ PathMode = kPathModeButtonsVals[0];
+ }
+ throw 1;
+}
+
+void CExtractDialog::GetOverwriteMode()
+{
+ for (int i = 0; i < kNumOverwriteButtons; i++)
+ if(IsButtonCheckedBool(kOverwriteButtons[i]))
+ {
+ OverwriteMode = kOverwriteButtonsVals[i];
+ return;
+ }
+ throw 0;
+}
+
+void CExtractDialog::SetOverwriteMode()
+{
+ for (int j = 0; j < 2; j++)
+ {
+ for (int i = 0; i < kNumOverwriteButtons; i++)
+ if(OverwriteMode == kOverwriteButtonsVals[i])
+ {
+ CheckRadioButton(kOverwriteButtons[0], kOverwriteButtons[kNumOverwriteButtons - 1],
+ kOverwriteButtons[i]);
+ return;
+ }
+ OverwriteMode = kOverwriteButtonsVals[0];
+ }
+ throw 1;
+}
+
+/*
+int CExtractDialog::GetFilesMode() const
+{
+ for (int i = 0; i < kNumFilesButtons; i++)
+ if(IsButtonCheckedBool(kFilesButtons[i]))
+ return i;
+ throw 0;
+}
+*/
+
+#endif
+
+#ifdef LANG
+static CIDLangPair kIDLangPairs[] =
+{
+ { IDC_STATIC_EXTRACT_EXTRACT_TO, 0x02000801 },
+ { IDC_EXTRACT_PATH_MODE, 0x02000810 },
+ { IDC_EXTRACT_RADIO_FULL_PATHNAMES, 0x02000811 },
+ { IDC_EXTRACT_RADIO_CURRENT_PATHNAMES, 0x02000812 },
+ { IDC_EXTRACT_RADIO_NO_PATHNAMES, 0x02000813 },
+ { IDC_EXTRACT_OVERWRITE_MODE, 0x02000820 },
+ { IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE, 0x02000821 },
+ { IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT, 0x02000822 },
+ { IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES, 0x02000823 },
+ { IDC_EXTRACT_RADIO_AUTO_RENAME, 0x02000824 },
+ { IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING, 0x02000825 },
+ { IDC_EXTRACT_FILES, 0x02000830 },
+ { IDC_EXTRACT_RADIO_SELECTED_FILES, 0x02000831 },
+ { IDC_EXTRACT_RADIO_ALL_FILES, 0x02000832 },
+ { IDC_EXTRACT_PASSWORD, 0x02000802 },
+ { IDC_EXTRACT_CHECK_SHOW_PASSWORD, 0x02000B02 },
+ { IDOK, 0x02000702 },
+ { IDCANCEL, 0x02000710 },
+ { IDHELP, 0x02000720 }
+
+};
+#endif
+
+// static const int kWildcardsButtonIndex = 2;
+
+static const int kHistorySize = 8;
+
+bool CExtractDialog::OnInit()
+{
+ #ifdef LANG
+ LangSetWindowText(HWND(*this), 0x02000800);
+ LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));
+ #endif
+ #ifndef _SFX
+ _passwordControl.Attach(GetItem(IDC_EXTRACT_EDIT_PASSWORD));
+ _passwordControl.SetText(Password);
+ _passwordControl.SetPasswordChar(TEXT('*'));
+ #endif
+
+ NExtract::CInfo extractionInfo;
+
+ #ifdef NO_REGISTRY
+ PathMode = NExtract::NPathMode::kFullPathnames;
+ OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
+ // extractionInfo.Paths = NExtract::NPathMode::kFullPathnames;
+ #else
+ ReadExtractionInfo(extractionInfo);
+ CheckButton(IDC_EXTRACT_CHECK_SHOW_PASSWORD, extractionInfo.ShowPassword);
+ UpdatePasswordControl();
+ PathMode = extractionInfo.PathMode;
+ OverwriteMode = extractionInfo.OverwriteMode;
+ #endif
+
+ _path.Attach(GetItem(IDC_EXTRACT_COMBO_PATH));
+
+ _path.SetText(DirectoryPath);
+
+ #ifndef NO_REGISTRY
+ for(int i = 0; i < extractionInfo.Paths.Size() && i < kHistorySize; i++)
+ _path.AddString(extractionInfo.Paths[i]);
+ #endif
+
+ /*
+ if(extractionInfo.Paths.Size() > 0)
+ _path.SetCurSel(0);
+ else
+ _path.SetCurSel(-1);
+ */
+
+
+
+ #ifndef _SFX
+ SetPathMode();
+ SetOverwriteMode();
+
+ /*
+ CheckRadioButton(kFilesButtons[0], kFilesButtons[kNumFilesButtons - 1],
+ kFilesButtons[_filesMode]);
+ */
+
+ // CWindow selectedFilesWindow = GetItem(IDC_EXTRACT_RADIO_SELECTED_FILES);
+ // selectedFilesWindow.Enable(_enableSelectedFilesButton);
+
+
+ #endif
+
+
+ // CWindow filesWindow = GetItem(IDC_EXTRACT_RADIO_FILES);
+ // filesWindow.Enable(_enableFilesButton);
+
+ // UpdateWildCardState();
+ return CModalDialog::OnInit();
+}
+
+#ifndef _SFX
+void CExtractDialog::UpdatePasswordControl()
+{
+ _passwordControl.SetPasswordChar((IsButtonChecked(
+ IDC_EXTRACT_CHECK_SHOW_PASSWORD) == BST_CHECKED) ? 0: TEXT('*'));
+ UString password;
+ _passwordControl.GetText(password);
+ _passwordControl.SetText(password);
+}
+#endif
+
+bool CExtractDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
+{
+ /*
+ for (int i = 0; i < kNumFilesButtons; i++)
+ if (buttonID == kFilesButtons[i])
+ {
+ UpdateWildCardState();
+ return true;
+ }
+ */
+ switch(buttonID)
+ {
+ case IDC_EXTRACT_BUTTON_SET_PATH:
+ OnButtonSetPath();
+ return true;
+ #ifndef _SFX
+ case IDC_EXTRACT_CHECK_SHOW_PASSWORD:
+ {
+ UpdatePasswordControl();
+ return true;
+ }
+ #endif
+ }
+ return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
+}
+
+void CExtractDialog::OnButtonSetPath()
+{
+ UString currentPath;
+ _path.GetText(currentPath);
+ UString title = LangStringSpec(IDS_EXTRACT_SET_FOLDER, 0x02000881);
+ UString resultPath;
+ if (!NShell::BrowseForFolder(HWND(*this), title, currentPath, resultPath))
+ return;
+ #ifndef NO_REGISTRY
+ _path.SetCurSel(-1);
+ #endif
+ _path.SetText(resultPath);
+}
+
+void AddUniqueString(UStringVector &list, const UString &s)
+{
+ for(int i = 0; i < list.Size(); i++)
+ if (s.CompareNoCase(list[i]) == 0)
+ return;
+ list.Add(s);
+}
+
+void CExtractDialog::OnOK()
+{
+ #ifndef _SFX
+ GetPathMode();
+ GetOverwriteMode();
+ // _filesMode = (NExtractionDialog::NFilesMode::EEnum)GetFilesMode();
+
+ _passwordControl.GetText(Password);
+ #endif
+
+ NExtract::CInfo extractionInfo;
+ extractionInfo.PathMode = PathMode;
+ extractionInfo.OverwriteMode = OverwriteMode;
+ extractionInfo.ShowPassword = (IsButtonChecked(
+ IDC_EXTRACT_CHECK_SHOW_PASSWORD) == BST_CHECKED);
+
+ UString s;
+
+ #ifdef NO_REGISTRY
+
+ _path.GetText(s);
+
+ #else
+
+ int currentItem = _path.GetCurSel();
+ if(currentItem == CB_ERR)
+ {
+ _path.GetText(s);
+ if(_path.GetCount() >= kHistorySize)
+ currentItem = _path.GetCount() - 1;
+ }
+ else
+ _path.GetLBText(currentItem, s);
+
+ #endif
+
+ s.Trim();
+ #ifndef _SFX
+ AddUniqueString(extractionInfo.Paths, s);
+ #endif
+ DirectoryPath = s;
+ #ifndef NO_REGISTRY
+ for(int i = 0; i < _path.GetCount(); i++)
+ if(i != currentItem)
+ {
+ UString sTemp;
+ _path.GetLBText(i, sTemp);
+ sTemp.Trim();
+ AddUniqueString(extractionInfo.Paths, sTemp);
+ }
+ SaveExtractionInfo(extractionInfo);
+ #endif
+ CModalDialog::OnOK();
+}
+
+/*
+void CExtractDialog::UpdateWildCardState()
+{
+ // UpdateData(TRUE);
+ // m_Wildcards.EnableWindow(BoolToBOOL(m_Files == kWildcardsButtonIndex));
+}
+*/
+
+#ifndef NO_REGISTRY
+static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/extract.htm";
+void CExtractDialog::OnHelp()
+{
+ ShowHelpWindow(NULL, kHelpTopic);
+ CModalDialog::OnHelp();
+}
+#endif
+
diff --git a/CPP/7zip/UI/GUI/ExtractDialog.h b/CPP/7zip/UI/GUI/ExtractDialog.h
new file mode 100755
index 00000000..0020c693
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractDialog.h
@@ -0,0 +1,77 @@
+// ExtractDialog.h
+
+#ifndef __EXTRACTDIALOG_H
+#define __EXTRACTDIALOG_H
+
+#include "resource.h"
+
+#include "Windows/Control/Dialog.h"
+#include "Windows/Control/Edit.h"
+#include "Windows/Control/ComboBox.h"
+
+#ifndef NO_REGISTRY
+#include "../Common/ZipRegistry.h"
+#endif
+#include "../Common/ExtractMode.h"
+
+namespace NExtractionDialog
+{
+ /*
+ namespace NFilesMode
+ {
+ enum EEnum
+ {
+ kSelected,
+ kAll,
+ kSpecified
+ };
+ }
+ */
+}
+
+class CExtractDialog: public NWindows::NControl::CModalDialog
+{
+ #ifdef NO_REGISTRY
+ NWindows::NControl::CDialogChildControl _path;
+ #else
+ NWindows::NControl::CComboBox _path;
+ #endif
+
+ #ifndef _SFX
+ NWindows::NControl::CEdit _passwordControl;
+ #endif
+
+ #ifndef _SFX
+ void GetPathMode();
+ void SetPathMode();
+ void GetOverwriteMode();
+ void SetOverwriteMode();
+ // int GetFilesMode() const;
+ void UpdatePasswordControl();
+ #endif
+
+ void OnButtonSetPath();
+
+ virtual bool OnInit();
+ virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
+ virtual void OnOK();
+ #ifndef NO_REGISTRY
+ virtual void OnHelp();
+ #endif
+public:
+ // bool _enableSelectedFilesButton;
+ // bool _enableFilesButton;
+ // NExtractionDialog::NFilesMode::EEnum FilesMode;
+
+ UString DirectoryPath;
+ #ifndef _SFX
+ UString Password;
+ #endif
+ NExtract::NPathMode::EEnum PathMode;
+ NExtract::NOverwriteMode::EEnum OverwriteMode;
+
+ INT_PTR Create(HWND aWndParent = 0)
+ { return CModalDialog::Create(IDD_DIALOG_EXTRACT, aWndParent); }
+};
+
+#endif
diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp
new file mode 100755
index 00000000..395df5a9
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp
@@ -0,0 +1,172 @@
+// ExtractGUI.cpp
+
+#include "StdAfx.h"
+
+#include "ExtractGUI.h"
+
+#include "Common/StringConvert.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/Error.h"
+#include "Windows/FileFind.h"
+#include "Windows/Thread.h"
+
+#include "../../FileManager/FormatUtils.h"
+#include "../../FileManager/ExtractCallback.h"
+#include "../../FileManager/LangUtils.h"
+
+#include "../Common/ArchiveExtractCallback.h"
+#include "../Explorer/MyMessages.h"
+#include "../Resource/Extract/resource.h"
+
+#include "OpenCallbackGUI.h"
+#include "ExtractDialog.h"
+
+using namespace NWindows;
+
+static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path";
+
+struct CThreadExtracting
+{
+ CExtractCallbackImp *ExtractCallbackSpec;
+
+ UStringVector *ArchivePaths;
+ UStringVector *ArchivePathsFull;
+ const NWildcard::CCensorNode *WildcardCensor;
+ const CExtractOptions *Options;
+ COpenCallbackGUI *OpenCallback;
+ CMyComPtr<IExtractCallbackUI> ExtractCallback;
+
+ UString ErrorMessage;
+ HRESULT Result;
+
+ DWORD Process()
+ {
+ ExtractCallbackSpec->ProgressDialog.WaitCreating();
+ try
+ {
+ Result = DecompressArchives(*ArchivePaths, *ArchivePathsFull,
+ *WildcardCensor, *Options, OpenCallback, ExtractCallback, ErrorMessage);
+ }
+ catch(const UString &s)
+ {
+ ErrorMessage = s;
+ Result = E_FAIL;
+ }
+ catch(const wchar_t *s)
+ {
+ ErrorMessage = s;
+ Result = E_FAIL;
+ }
+ catch(const char *s)
+ {
+ ErrorMessage = GetUnicodeString(s);
+ Result = E_FAIL;
+ }
+ catch(...)
+ {
+ Result = E_FAIL;
+ }
+ ExtractCallbackSpec->ProgressDialog.MyClose();
+ return 0;
+ }
+ static DWORD WINAPI MyThreadFunction(void *param)
+ {
+ return ((CThreadExtracting *)param)->Process();
+ }
+};
+
+HRESULT ExtractGUI(
+ UStringVector &archivePaths,
+ UStringVector &archivePathsFull,
+ const NWildcard::CCensorNode &wildcardCensor,
+ CExtractOptions &options,
+ bool showDialog,
+ COpenCallbackGUI *openCallback,
+ CExtractCallbackImp *extractCallback)
+{
+ CThreadExtracting extracter;
+
+ if (!options.TestMode)
+ {
+ UString outputDir = options.OutputDir;
+ if (outputDir.IsEmpty())
+ NFile::NDirectory::MyGetCurrentDirectory(outputDir);
+ if (showDialog)
+ {
+ CExtractDialog dialog;
+ if (!NFile::NDirectory::MyGetFullPathName(outputDir, dialog.DirectoryPath))
+ {
+ MyMessageBox(kIncorrectOutDir);
+ return E_FAIL;
+ }
+ NFile::NName::NormalizeDirPathPrefix(dialog.DirectoryPath);
+
+ // dialog.OverwriteMode = options.OverwriteMode;
+ // dialog.PathMode = options.PathMode;
+
+ if(dialog.Create(0) != IDOK)
+ return E_ABORT;
+ outputDir = dialog.DirectoryPath;
+ options.OverwriteMode = dialog.OverwriteMode;
+ options.PathMode = dialog.PathMode;
+ #ifndef _SFX
+ openCallback->Password = dialog.Password;
+ openCallback->PasswordIsDefined = !dialog.Password.IsEmpty();
+ #endif
+ }
+ if (!NFile::NDirectory::MyGetFullPathName(outputDir, options.OutputDir))
+ {
+ MyMessageBox(kIncorrectOutDir);
+ return E_FAIL;
+ }
+ NFile::NName::NormalizeDirPathPrefix(options.OutputDir);
+
+ /*
+ if(!NFile::NDirectory::CreateComplexDirectory(options.OutputDir))
+ {
+ UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError()));
+ UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,
+ #ifdef LANG
+ 0x02000603,
+ #endif
+ options.OutputDir);
+ MyMessageBox(s2 + UString(L"\n") + s);
+ return E_FAIL;
+ }
+ */
+ }
+
+ UString title = LangStringSpec(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING,
+ options.TestMode ? 0x02000F90: 0x02000890);
+
+ extracter.ExtractCallbackSpec = extractCallback;
+ extracter.ExtractCallback = extractCallback;
+ extracter.ExtractCallbackSpec->Init();
+
+ extracter.ArchivePaths = &archivePaths;
+ extracter.ArchivePathsFull = &archivePathsFull;
+ extracter.WildcardCensor = &wildcardCensor;
+ extracter.Options = &options;
+ extracter.OpenCallback = openCallback;
+
+ CThread thread;
+ if (!thread.Create(CThreadExtracting::MyThreadFunction, &extracter))
+ throw 271824;
+ extracter.ExtractCallbackSpec->StartProgressDialog(title);
+ if (extracter.Result == S_OK && options.TestMode &&
+ extracter.ExtractCallbackSpec->Messages.IsEmpty() &&
+ extracter.ExtractCallbackSpec->NumArchiveErrors == 0)
+ {
+ #ifndef _SFX
+ MessageBoxW(0, LangString(IDS_MESSAGE_NO_ERRORS, 0x02000608),
+ LangString(IDS_PROGRESS_TESTING, 0x02000F90), 0);
+ #endif
+ }
+ if (extracter.Result != S_OK)
+ if (!extracter.ErrorMessage.IsEmpty())
+ throw extracter.ErrorMessage;
+ return extracter.Result;
+}
+
+
diff --git a/CPP/7zip/UI/GUI/ExtractGUI.h b/CPP/7zip/UI/GUI/ExtractGUI.h
new file mode 100755
index 00000000..5a0b157d
--- /dev/null
+++ b/CPP/7zip/UI/GUI/ExtractGUI.h
@@ -0,0 +1,20 @@
+// GUI/ExtractGUI.h
+
+#ifndef __EXTRACT_GUI_H
+#define __EXTRACT_GUI_H
+
+#include "../Common/Extract.h"
+#include "OpenCallbackGUI.h"
+
+#include "../../FileManager/ExtractCallback.h"
+
+HRESULT ExtractGUI(
+ UStringVector &archivePaths,
+ UStringVector &archivePathsFull,
+ const NWildcard::CCensorNode &wildcardCensor,
+ CExtractOptions &options,
+ bool showDialog,
+ COpenCallbackGUI *openCallback,
+ CExtractCallbackImp *extractCallback);
+
+#endif
diff --git a/CPP/7zip/UI/GUI/FM.ico b/CPP/7zip/UI/GUI/FM.ico
new file mode 100755
index 00000000..3a0a34da
--- /dev/null
+++ b/CPP/7zip/UI/GUI/FM.ico
Binary files differ
diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp
new file mode 100755
index 00000000..fe956dbd
--- /dev/null
+++ b/CPP/7zip/UI/GUI/GUI.cpp
@@ -0,0 +1,260 @@
+// GUI.cpp
+
+#include "StdAfx.h"
+
+#include <initguid.h>
+
+#include "Common/NewHandler.h"
+#include "Common/StringConvert.h"
+#include "Common/CommandLineParser.h"
+#include "Common/Exception.h"
+
+#include "Windows/COM.h"
+#include "Windows/FileMapping.h"
+#include "Windows/FileDir.h"
+#include "Windows/Synchronization.h"
+#include "Windows/Error.h"
+#include "Windows/FileName.h"
+#ifdef _WIN32
+#include "Windows/MemoryLock.h"
+#include "Common/Alloc.h"
+#endif
+
+#include "../../IStream.h"
+#include "../../IPassword.h"
+
+#include "../../FileManager/StringUtils.h"
+
+#include "../Common/ExitCode.h"
+#include "../Common/ArchiveCommandLine.h"
+
+#include "../Resource/Extract/resource.h"
+#include "../Explorer/MyMessages.h"
+
+#include "ExtractGUI.h"
+#include "UpdateGUI.h"
+
+using namespace NWindows;
+
+HINSTANCE g_hInstance;
+#ifndef _UNICODE
+bool g_IsNT = false;
+#endif
+
+static const wchar_t *kExceptionErrorMessage = L"Error:";
+static const wchar_t *kUserBreak = L"Break signaled";
+
+static const wchar_t *kMemoryExceptionMessage = L"ERROR: Can't allocate required memory!";
+static const wchar_t *kUnknownExceptionMessage = L"Unknown Error";
+static const wchar_t *kInternalExceptionMessage = L"Internal Error #";
+
+static const wchar_t *kIncorrectCommandMessage = L"Incorrect command";
+
+static void ErrorMessage(const wchar_t *message)
+{
+ MessageBoxW(0, message, L"7-Zip GUI", MB_ICONERROR);
+}
+
+int Main2()
+{
+ /*
+ TCHAR t[512];
+ GetCurrentDirectory(512, t);
+ ErrorMessage(t);
+ return 0;
+ */
+
+ UStringVector commandStrings;
+ NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
+ if(commandStrings.Size() <= 1)
+ {
+ MessageBoxW(0, L"Specify command", L"7-Zip", 0);
+ return 0;
+ }
+ commandStrings.Delete(0);
+
+ CArchiveCommandLineOptions options;
+ CArchiveCommandLineParser parser;
+
+ parser.Parse1(commandStrings, options);
+ parser.Parse2(options);
+
+ #ifdef _WIN32
+ if (options.LargePages)
+ NSecurity::EnableLockMemoryPrivilege();
+ #endif
+
+ bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
+
+ if (isExtractGroupCommand)
+ {
+ CExtractCallbackImp *ecs = new CExtractCallbackImp;
+ CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
+ ecs->PasswordIsDefined = options.PasswordEnabled;
+ ecs->Password = options.Password;
+ ecs->Init();
+
+ COpenCallbackGUI openCallback;
+ openCallback.PasswordIsDefined = options.PasswordEnabled;
+ openCallback.Password = options.Password;
+
+ CExtractOptions eo;
+ eo.StdOutMode = options.StdOutMode;
+ eo.OutputDir = options.OutputDir;
+ eo.YesToAll = options.YesToAll;
+ eo.OverwriteMode = options.OverwriteMode;
+ eo.PathMode = options.Command.GetPathMode();
+ eo.TestMode = options.Command.IsTestMode();
+ #ifdef COMPRESS_MT
+ eo.Properties = options.ExtractProperties;
+ #endif
+
+ HRESULT result = ExtractGUI(
+ options.ArchivePathsSorted,
+ options.ArchivePathsFullSorted,
+ options.WildcardCensor.Pairs.Front().Head,
+ eo, options.ShowDialog, &openCallback, ecs);
+ if (result != S_OK)
+ throw CSystemException(result);
+ if (ecs->Messages.Size() > 0 || ecs->NumArchiveErrors != 0)
+ return NExitCode::kFatalError;
+ }
+ else if (options.Command.IsFromUpdateGroup())
+ {
+ bool passwordIsDefined =
+ options.PasswordEnabled && !options.Password.IsEmpty();
+
+ COpenCallbackGUI openCallback;
+ openCallback.PasswordIsDefined = passwordIsDefined;
+ openCallback.Password = options.Password;
+
+ CUpdateCallbackGUI callback;
+ // callback.EnablePercents = options.EnablePercents;
+ callback.PasswordIsDefined = passwordIsDefined;
+ callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();
+ callback.Password = options.Password;
+ // callback.StdOutMode = options.UpdateOptions.StdOutMode;
+ callback.Init();
+
+ CUpdateErrorInfo errorInfo;
+
+ HRESULT result = UpdateGUI(
+ options.WildcardCensor, options.UpdateOptions,
+ options.ShowDialog,
+ errorInfo, &openCallback, &callback);
+
+ if (result != S_OK)
+ {
+ if (!errorInfo.Message.IsEmpty())
+ ErrorMessage(errorInfo.Message);
+ throw CSystemException(result);
+ }
+ if (callback.FailedFiles.Size() > 0)
+ return NExitCode::kWarning;
+ }
+ else
+ {
+ ErrorMessage(L"Use correct command");
+ return 0;
+ }
+ return 0;
+}
+
+static bool inline IsItWindowsNT()
+{
+ OSVERSIONINFO versionInfo;
+ versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+ if (!::GetVersionEx(&versionInfo))
+ return false;
+ return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int /* nCmdShow */)
+{
+ g_hInstance = hInstance;
+ #ifdef _UNICODE
+ if (!IsItWindowsNT())
+ {
+ MyMessageBox(L"This program requires Windows NT/2000/XP/2003");
+ return NExitCode::kFatalError;
+ }
+ #else
+ g_IsNT = IsItWindowsNT();
+ #endif
+
+ #ifdef _WIN32
+ SetLargePageSize();
+ #endif
+
+ InitCommonControls();
+
+ ReloadLang();
+
+ // setlocale(LC_COLLATE, ".ACP");
+ try
+ {
+ return Main2();
+ }
+ catch(const CNewException &)
+ {
+ MyMessageBox(kMemoryExceptionMessage);
+ return (NExitCode::kMemoryError);
+ }
+ catch(const CArchiveCommandLineException &e)
+ {
+ MyMessageBox(GetUnicodeString(e));
+ return (NExitCode::kUserError);
+ }
+ catch(const CSystemException &systemError)
+ {
+ if (systemError.ErrorCode == E_OUTOFMEMORY)
+ {
+ MyMessageBox(kMemoryExceptionMessage);
+ return (NExitCode::kMemoryError);
+ }
+ if (systemError.ErrorCode == E_ABORT)
+ {
+ // MyMessageBox(kUserBreak);
+ return (NExitCode::kUserBreak);
+ }
+ UString message;
+ NError::MyFormatMessage(systemError.ErrorCode, message);
+ MyMessageBox(message);
+ return (NExitCode::kFatalError);
+ }
+ /*
+ catch(NExitCode::EEnum &exitCode)
+ {
+ g_StdErr << kInternalExceptionMessage << exitCode << endl;
+ return (exitCode);
+ }
+ */
+ catch(const UString &s)
+ {
+ MyMessageBox(s);
+ return (NExitCode::kFatalError);
+ }
+ catch(const AString &s)
+ {
+ MyMessageBox(GetUnicodeString(s));
+ return (NExitCode::kFatalError);
+ }
+ catch(const char *s)
+ {
+ MyMessageBox(GetUnicodeString(s));
+ return (NExitCode::kFatalError);
+ }
+ /*
+ catch(int t)
+ {
+ g_StdErr << kInternalExceptionMessage << t << endl;
+ return (NExitCode::kFatalError);
+ }
+ */
+ catch(...)
+ {
+ MyMessageBox(kUnknownExceptionMessage);
+ return (NExitCode::kFatalError);
+ }
+}
+
diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp
new file mode 100755
index 00000000..dadb9648
--- /dev/null
+++ b/CPP/7zip/UI/GUI/GUI.dsp
@@ -0,0 +1,904 @@
+# Microsoft Developer Studio Project File - Name="GUI" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=GUI - Win32 DebugU
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "GUI.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "GUI.mak" CFG="GUI - Win32 DebugU"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "GUI - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "GUI - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "GUI - Win32 ReleaseU" (based on "Win32 (x86) Application")
+!MESSAGE "GUI - Win32 DebugU" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "GUI - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-Zip\7zg.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "GUI - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-Zip\7zg.exe" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "GUI - Win32 ReleaseU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseU"
+# PROP BASE Intermediate_Dir "ReleaseU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseU"
+# PROP Intermediate_Dir "ReleaseU"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\UTIL\7zg.exe"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Program Files\7-Zip\7zgn.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "GUI - Win32 DebugU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DebugU"
+# PROP BASE Intermediate_Dir "DebugU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugU"
+# PROP Intermediate_Dir "DebugU"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "COMPRESS_MT" /D "WIN_LONG_PATH" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zg.exe" /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Program Files\7-Zip\7zgn.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "GUI - Win32 Release"
+# Name "GUI - Win32 Debug"
+# Name "GUI - Win32 ReleaseU"
+# Name "GUI - Win32 DebugU"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\7zG.exe.manifest
+# End Source File
+# Begin Source File
+
+SOURCE=.\FM.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "SDK"
+
+# PROP Default_Filter ""
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\Alloc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Alloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Lang.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Lang.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ListFileUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ListFileUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\TextConfig.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\TextConfig.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Group "Control"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\ComboBox.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\ComboBox.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\Dialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\Dialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\Edit.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\ListView.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\ListView.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\ProgressBar.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\Windows\CommonDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\CommonDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Error.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\MemoryLock.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\MemoryLock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Registry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Registry.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ResourceString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ResourceString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Shell.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Shell.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Window.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Window.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "UI Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\ArchiveCommandLine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveCommandLine.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveExtractCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveOpenCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiveOpenCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiverInfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ArchiverInfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DefaultName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DefaultName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DirItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\EnumDirItems.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\EnumDirItems.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExitCode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\Extract.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\Extract.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExtractingFilePath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExtractingFilePath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ExtractMode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\HandlerLoader.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\IFileExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\OpenArchive.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\OpenArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\Property.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\PropIDUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\PropIDUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SetProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SetProperties.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SortUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\SortUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\TempFiles.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\TempFiles.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\Update.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\Update.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateAction.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateAction.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdatePair.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdatePair.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateProduce.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\UpdateProduce.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\WorkDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\WorkDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ZipRegistry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ZipRegistry.h
+# End Source File
+# End Group
+# Begin Group "Explorer"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Explorer\MyMessages.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Explorer\MyMessages.h
+# End Source File
+# End Group
+# Begin Group "Dialogs"
+
+# PROP Default_Filter ""
+# Begin Group "Progress"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\FileManager\Resource\ProgressDialog2\ProgressDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\Resource\ProgressDialog2\ProgressDialog.h
+# End Source File
+# End Group
+# Begin Group "Messages"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\FileManager\Resource\MessagesDialog\MessagesDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\Resource\MessagesDialog\MessagesDialog.h
+# End Source File
+# End Group
+# Begin Group "Overwtite"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\FileManager\Resource\OverwriteDialog\OverwriteDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\Resource\OverwriteDialog\OverwriteDialog.h
+# End Source File
+# End Group
+# Begin Group "Password"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\FileManager\Resource\PasswordDialog\PasswordDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\Resource\PasswordDialog\PasswordDialog.h
+# End Source File
+# End Group
+# Begin Group "Compress Dialog"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\CompressDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CompressDialog.h
+# End Source File
+# End Group
+# Begin Group "Extract Dialog"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ExtractDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ExtractDialog.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "FM Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\FileManager\ExtractCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\ExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\FolderInterface.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\FormatUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\FormatUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\HelpUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\HelpUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\LangUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\LangUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\OpenCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\OpenCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\ProgramLocation.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\ProgramLocation.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\RegistryUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\RegistryUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\SplitUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\SplitUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\StringUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\StringUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\UpdateCallback100.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\FileManager\UpdateCallback100.h
+# End Source File
+# End Group
+# Begin Group "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ExtractGUI.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ExtractGUI.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\GUI.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OpenCallbackGUI.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OpenCallbackGUI.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\UpdateCallbackGUI.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\UpdateCallbackGUI.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\UpdateGUI.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\UpdateGUI.h
+# End Source File
+# End Group
+# Begin Group "7-zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\FilePathAutoRename.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FilePathAutoRename.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/CPP/7zip/UI/GUI/GUI.dsw b/CPP/7zip/UI/GUI/GUI.dsw
new file mode 100755
index 00000000..85d33484
--- /dev/null
+++ b/CPP/7zip/UI/GUI/GUI.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "GUI"=.\GUI.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/UI/GUI/OpenCallbackGUI.cpp b/CPP/7zip/UI/GUI/OpenCallbackGUI.cpp
new file mode 100755
index 00000000..bc6cf393
--- /dev/null
+++ b/CPP/7zip/UI/GUI/OpenCallbackGUI.cpp
@@ -0,0 +1,65 @@
+// OpenCallbackGUI.cpp
+
+#include "StdAfx.h"
+
+#include "OpenCallbackGUI.h"
+
+#include "Common/StdOutStream.h"
+#include "Common/StdInStream.h"
+#include "Common/StringConvert.h"
+
+#ifndef _NO_CRYPTO
+#include "../../FileManager/Resource/PasswordDialog/PasswordDialog.h"
+#endif
+
+HRESULT COpenCallbackGUI::CheckBreak()
+{
+ return S_OK;
+}
+
+HRESULT COpenCallbackGUI::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
+{
+ return S_OK;
+}
+
+HRESULT COpenCallbackGUI::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */)
+{
+ return S_OK;
+}
+
+#ifndef _NO_CRYPTO
+HRESULT COpenCallbackGUI::CryptoGetTextPassword(BSTR *password)
+{
+ PasswordWasAsked = true;
+ if (!PasswordIsDefined)
+ {
+ CPasswordDialog dialog;
+ if (dialog.Create(ParentWindow) == IDCANCEL)
+ return E_ABORT;
+ Password = dialog.Password;
+ PasswordIsDefined = true;
+ }
+ CMyComBSTR tempName(Password);
+ *password = tempName.Detach();
+ return S_OK;
+}
+
+HRESULT COpenCallbackGUI::GetPasswordIfAny(UString &password)
+{
+ if (PasswordIsDefined)
+ password = Password;
+ return S_OK;
+}
+
+bool COpenCallbackGUI::WasPasswordAsked()
+{
+ return PasswordWasAsked;
+}
+
+void COpenCallbackGUI::ClearPasswordWasAskedFlag()
+{
+ PasswordWasAsked = false;
+}
+
+#endif
+
diff --git a/CPP/7zip/UI/GUI/OpenCallbackGUI.h b/CPP/7zip/UI/GUI/OpenCallbackGUI.h
new file mode 100755
index 00000000..6b531d3c
--- /dev/null
+++ b/CPP/7zip/UI/GUI/OpenCallbackGUI.h
@@ -0,0 +1,35 @@
+// OpenCallbackGUI.h
+
+#ifndef __OPEN_CALLBACK_GUI_H
+#define __OPEN_CALLBACK_GUI_H
+
+#include "../Common/ArchiveOpenCallback.h"
+
+class COpenCallbackGUI: public IOpenCallbackUI
+{
+public:
+ HRESULT CheckBreak();
+ HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes);
+ HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes);
+ #ifndef _NO_CRYPTO
+ HRESULT CryptoGetTextPassword(BSTR *password);
+ HRESULT GetPasswordIfAny(UString &password);
+ bool WasPasswordAsked();
+ void ClearPasswordWasAskedFlag();
+
+ bool PasswordIsDefined;
+ UString Password;
+ bool PasswordWasAsked;
+ #endif
+
+ HWND ParentWindow;
+
+ COpenCallbackGUI():
+ #ifndef _NO_CRYPTO
+ PasswordIsDefined(false),
+ PasswordWasAsked(false),
+ #endif
+ ParentWindow(0) {}
+};
+
+#endif
diff --git a/CPP/7zip/UI/GUI/StdAfx.cpp b/CPP/7zip/UI/GUI/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/UI/GUI/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/UI/GUI/StdAfx.h b/CPP/7zip/UI/GUI/StdAfx.h
new file mode 100755
index 00000000..46ea51cf
--- /dev/null
+++ b/CPP/7zip/UI/GUI/StdAfx.h
@@ -0,0 +1,13 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include <windows.h>
+#include <commctrl.h>
+#include <shlobj.h>
+#include <stdio.h>
+
+#include "Common/NewHandler.h"
+
+#endif
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp
new file mode 100755
index 00000000..eff29953
--- /dev/null
+++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp
@@ -0,0 +1,167 @@
+// UpdateCallbackGUI.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateCallbackGUI.h"
+
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+#include "Common/Defs.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Error.h"
+#include "../../FileManager/Resource/MessagesDialog/MessagesDialog.h"
+#include "../../FileManager/Resource/PasswordDialog/PasswordDialog.h"
+
+using namespace NWindows;
+
+CUpdateCallbackGUI::~CUpdateCallbackGUI()
+{
+ if (!Messages.IsEmpty())
+ {
+ CMessagesDialog messagesDialog;
+ messagesDialog.Messages = &Messages;
+ messagesDialog.Create(ParentWindow);
+ }
+}
+
+void CUpdateCallbackGUI::Init()
+{
+ FailedFiles.Clear();
+ Messages.Clear();
+ NumArchiveErrors = 0;
+}
+
+void CUpdateCallbackGUI::AddErrorMessage(LPCWSTR message)
+{
+ Messages.Add(message);
+}
+
+void CUpdateCallbackGUI::AddErrorMessage(const wchar_t *name, DWORD systemError)
+{
+ AddErrorMessage(
+ UString(L"WARNING: ") +
+ NError::MyFormatMessageW(systemError) +
+ UString(L": ") +
+ UString(name));
+}
+
+HRESULT CUpdateCallbackGUI::OpenResult(const wchar_t *name, HRESULT result)
+{
+ if (result != S_OK)
+ {
+ AddErrorMessage (UString(L"Error: ") + name +
+ UString(L" is not supported archive"));
+ }
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::StartScanning()
+{
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::CanNotFindError(const wchar_t *name, DWORD systemError)
+{
+ FailedFiles.Add(name);
+ AddErrorMessage(name, systemError);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::FinishScanning()
+{
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::StartArchive(const wchar_t *name, bool /* updating */)
+{
+ ProgressDialog.ProgressSynch.SetTitleFileName(name);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::FinishArchive()
+{
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::CheckBreak()
+{
+ for (;;)
+ {
+ if(ProgressDialog.ProgressSynch.GetStopped())
+ return E_ABORT;
+ if(!ProgressDialog.ProgressSynch.GetPaused())
+ break;
+ ::Sleep(100);
+ }
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::Finilize()
+{
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::SetTotal(UInt64 total)
+{
+ ProgressDialog.ProgressSynch.SetProgress(total, 0);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::SetCompleted(const UInt64 *completeValue)
+{
+ RINOK(CheckBreak());
+ if (completeValue != NULL)
+ ProgressDialog.ProgressSynch.SetPos(*completeValue);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::GetStream(const wchar_t *name, bool /* isAnti */)
+{
+ ProgressDialog.ProgressSynch.SetCurrentFileName(name);
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::OpenFileError(const wchar_t *name, DWORD systemError)
+{
+ FailedFiles.Add(name);
+ // if (systemError == ERROR_SHARING_VIOLATION)
+ {
+ AddErrorMessage(name, systemError);
+ return S_FALSE;
+ }
+ // return systemError;
+}
+
+HRESULT CUpdateCallbackGUI::SetOperationResult(Int32 /* operationResult */)
+{
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
+{
+ if (!PasswordIsDefined)
+ {
+ if (AskPassword)
+ {
+ CPasswordDialog dialog;
+ if (dialog.Create(ParentWindow) == IDCANCEL)
+ return E_ABORT;
+ Password = dialog.Password;
+ PasswordIsDefined = true;
+ }
+ }
+ *passwordIsDefined = BoolToInt(PasswordIsDefined);
+ CMyComBSTR tempName(Password);
+ *password = tempName.Detach();
+ return S_OK;
+}
+
+/*
+It doesn't work, since main stream waits Dialog
+HRESULT CUpdateCallbackGUI::CloseProgress()
+{
+ ProgressDialog.MyClose();
+ return S_OK;
+};
+*/ \ No newline at end of file
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.h b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h
new file mode 100755
index 00000000..16f0220c
--- /dev/null
+++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h
@@ -0,0 +1,63 @@
+// UpdateCallbackGUI.h
+
+#ifndef __UPDATE_CALLBACK_GUI_H
+#define __UPDATE_CALLBACK_GUI_H
+
+#include "../Common/Update.h"
+#include "../../FileManager/Resource/ProgressDialog2/ProgressDialog.h"
+
+class CUpdateCallbackGUI: public IUpdateCallbackUI2
+{
+public:
+ // bool StdOutMode;
+ bool PasswordIsDefined;
+ UString Password;
+ bool AskPassword;
+
+ CUpdateCallbackGUI():
+ PasswordIsDefined(false),
+ AskPassword(false),
+ // StdOutMode(false)
+ ParentWindow(0)
+ {}
+
+ ~CUpdateCallbackGUI();
+ void Init();
+
+ HRESULT OpenResult(const wchar_t *name, HRESULT result);
+
+ HRESULT StartScanning();
+ HRESULT CanNotFindError(const wchar_t *name, DWORD systemError);
+ HRESULT FinishScanning();
+
+ HRESULT StartArchive(const wchar_t *name, bool updating);
+ HRESULT FinishArchive();
+
+ HRESULT CheckBreak();
+ HRESULT Finilize();
+ HRESULT SetTotal(UInt64 total);
+ HRESULT SetCompleted(const UInt64 *completeValue);
+
+ HRESULT GetStream(const wchar_t *name, bool isAnti);
+ HRESULT OpenFileError(const wchar_t *name, DWORD systemError);
+ HRESULT SetOperationResult(Int32 operationResult);
+ HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password);
+
+ // HRESULT CloseProgress();
+
+ UStringVector FailedFiles;
+
+ CProgressDialog ProgressDialog;
+ HWND ParentWindow;
+ void StartProgressDialog(const UString &title)
+ {
+ ProgressDialog.Create(title, ParentWindow);
+ }
+
+ UStringVector Messages;
+ int NumArchiveErrors;
+ void AddErrorMessage(LPCWSTR message);
+ void AddErrorMessage(const wchar_t *name, DWORD systemError);
+};
+
+#endif
diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp
new file mode 100755
index 00000000..e39e7faf
--- /dev/null
+++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp
@@ -0,0 +1,397 @@
+// UpdateGUI.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateGUI.h"
+
+#include "resource.h"
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+#include "Common/StringToInt.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/Error.h"
+#include "Windows/FileFind.h"
+#include "Windows/Thread.h"
+
+#include "../../FileManager/FormatUtils.h"
+#include "../../FileManager/ExtractCallback.h"
+#include "../../FileManager/StringUtils.h"
+
+#include "../Common/ArchiveExtractCallback.h"
+#include "../Common/WorkDir.h"
+#include "../Explorer/MyMessages.h"
+#include "../Resource/Extract/resource.h"
+
+#include "OpenCallbackGUI.h"
+#include "CompressDialog.h"
+#include "UpdateGUI.h"
+
+using namespace NWindows;
+using namespace NFile;
+
+static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path";
+static const wchar_t *kDefaultSfxModule = L"7z.sfx";
+static const wchar_t *kSFXExtension = L"exe";
+
+struct CThreadUpdating
+{
+ CUpdateCallbackGUI *UpdateCallbackGUI;
+
+ const NWildcard::CCensor *WildcardCensor;
+ CUpdateOptions *Options;
+ COpenCallbackGUI *OpenCallback;
+
+ CUpdateErrorInfo *ErrorInfo;
+ HRESULT Result;
+
+ DWORD Process()
+ {
+ UpdateCallbackGUI->ProgressDialog.WaitCreating();
+ try
+ {
+ Result = UpdateArchive(*WildcardCensor, *Options,
+ *ErrorInfo, OpenCallback, UpdateCallbackGUI);
+ }
+ catch(const UString &s)
+ {
+ ErrorInfo->Message = s;
+ Result = E_FAIL;
+ }
+ catch(const wchar_t *s)
+ {
+ ErrorInfo->Message = s;
+ Result = E_FAIL;
+ }
+ catch(const char *s)
+ {
+ ErrorInfo->Message = GetUnicodeString(s);
+ Result = E_FAIL;
+ }
+ catch(...)
+ {
+ Result = E_FAIL;
+ }
+ UpdateCallbackGUI->ProgressDialog.MyClose();
+ return 0;
+ }
+ static DWORD WINAPI MyThreadFunction(void *param)
+ {
+ return ((CThreadUpdating *)param)->Process();
+ }
+};
+
+static void AddProp(CObjectVector<CProperty> &properties,
+ const UString &name, const UString &value)
+{
+ CProperty prop;
+ prop.Name = name;
+ prop.Value = value;
+ properties.Add(prop);
+}
+
+static void AddProp(CObjectVector<CProperty> &properties,
+ const UString &name, UInt32 value)
+{
+ wchar_t tmp[32];
+ ConvertUInt64ToString(value, tmp);
+ AddProp(properties, name, tmp);
+}
+
+static void AddProp(CObjectVector<CProperty> &properties,
+ const UString &name, bool value)
+{
+ AddProp(properties, name, value ? UString(L"on"): UString(L"off"));
+}
+
+static bool IsThereMethodOverride(bool is7z, const UString &propertiesString)
+{
+ UStringVector strings;
+ SplitString(propertiesString, strings);
+ for (int i = 0; i < strings.Size(); i++)
+ {
+ 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.Length() > 0)
+ if (s[0] == L'm' && s[1] == L'=')
+ return true;
+ }
+ }
+ return false;
+}
+
+static void ParseAndAddPropertires(CObjectVector<CProperty> &properties,
+ const UString &propertiesString)
+{
+ UStringVector strings;
+ SplitString(propertiesString, strings);
+ for (int i = 0; i < strings.Size(); i++)
+ {
+ const UString &s = strings[i];
+ CProperty property;
+ int index = s.Find(L'=');
+ if (index < 0)
+ property.Name = s;
+ else
+ {
+ property.Name = s.Left(index);
+ property.Value = s.Mid(index + 1);
+ }
+ properties.Add(property);
+ }
+}
+
+static void SetOutProperties(
+ CObjectVector<CProperty> &properties,
+ bool is7z,
+ UInt32 level,
+ bool setMethod,
+ const UString &method,
+ UInt32 dictionary,
+ bool orderMode,
+ UInt32 order,
+ bool solidModeIsAllowed, bool solidMode,
+ bool multiThreadIsAllowed, bool multiThread,
+ const UString &encryptionMethod,
+ bool encryptHeadersIsAllowed, bool encryptHeaders,
+ bool /* sfxMode */)
+{
+ if (level != (UInt32)(Int32)-1)
+ AddProp(properties, L"x", (UInt32)level);
+ if (setMethod)
+ {
+ if (!method.IsEmpty())
+ AddProp(properties, is7z ? L"0": L"m", method);
+ if (dictionary != (UInt32)(Int32)-1)
+ {
+ UString name;
+ if (is7z)
+ name = L"0";
+ if (orderMode)
+ name += L"mem";
+ else
+ name += L"d";
+ wchar_t s[32];
+ ConvertUInt64ToString(dictionary, s);
+ size_t len = wcslen(s);
+ s[len++] = L'B';
+ s[len] = L'\0';
+ AddProp(properties, name, UString(s));
+ }
+ if (order != (UInt32)(Int32)-1)
+ {
+ UString name;
+ if (is7z)
+ name = L"0";
+ if (orderMode)
+ name += L"o";
+ else
+ name += L"fb";
+ AddProp(properties, name, (UInt32)order);
+ }
+ }
+
+ if (!encryptionMethod.IsEmpty())
+ AddProp(properties, L"em", encryptionMethod);
+
+ if (encryptHeadersIsAllowed)
+ AddProp(properties, L"he", encryptHeaders);
+ if (solidModeIsAllowed)
+ AddProp(properties, L"s", solidMode);
+ if (multiThreadIsAllowed)
+ AddProp(properties, L"mt", multiThread);
+}
+
+static HRESULT ShowDialog(const NWildcard::CCensor &censor,
+ CUpdateOptions &options, CUpdateCallbackGUI *callback)
+{
+ if (options.Commands.Size() != 1)
+ throw "It must be one command";
+ CObjectVector<CArchiverInfo> archivers;
+ CArchiverInfo archiverInfo;
+ ReadArchiverInfoList(archivers);
+ UString currentDirPrefix;
+ {
+ if (!NDirectory::MyGetCurrentDirectory(currentDirPrefix))
+ return E_FAIL;
+ NName::NormalizeDirPathPrefix(currentDirPrefix);
+ }
+
+ bool oneFile = false;
+ NFind::CFileInfoW fileInfo;
+ 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)
+ {
+ UString name = pair.Prefix;
+ for (int i = 0; i < item.PathParts.Size(); i++)
+ {
+ if (i > 0)
+ name += L'\\';
+ name += item.PathParts[i];
+ }
+ if (NFind::FindFile(name, fileInfo))
+ {
+ if (censor.Pairs.Size() == 1 && pair.Head.IncludeItems.Size() == 1)
+ oneFile = !fileInfo.IsDirectory();
+ }
+ }
+ }
+ }
+
+ CCompressDialog dialog;
+ NCompressDialog::CInfo &di = dialog.Info;
+ for(int i = 0; i < archivers.Size(); i++)
+ {
+ const CArchiverInfo &ai = archivers[i];
+ if (ai.UpdateEnabled && (oneFile || !ai.KeepName))
+ dialog.m_ArchiverInfoList.Add(ai);
+ }
+ if(dialog.m_ArchiverInfoList.Size() == 0)
+ {
+ MyMessageBox(L"No Update Engines");
+ return E_FAIL;
+ }
+
+ // di.ArchiveName = options.ArchivePath.GetFinalPath();
+ di.ArchiveName = options.ArchivePath.GetPathWithoutExt();
+ dialog.OriginalFileName = fileInfo.Name;
+
+ di.CurrentDirPrefix = currentDirPrefix;
+ di.SFXMode = options.SfxMode;
+
+ di.Solid = true;
+ di.MultiThread = false;
+
+ if (callback->PasswordIsDefined)
+ di.Password = callback->Password;
+
+ di.KeepName = !oneFile;
+
+ if(dialog.Create(0) != IDOK)
+ return E_ABORT;
+
+ options.VolumesSizes = di.VolumeSizes;
+ /*
+ if (di.VolumeSizeIsDefined)
+ {
+ MyMessageBox(L"Splitting to volumes is not supported");
+ return E_FAIL;
+ }
+ */
+
+ NUpdateArchive::CActionSet &actionSet = options.Commands.Front().ActionSet;
+
+ switch(di.UpdateMode)
+ {
+ case NCompressDialog::NUpdateMode::kAdd:
+ actionSet = NUpdateArchive::kAddActionSet;
+ break;
+ case NCompressDialog::NUpdateMode::kUpdate:
+ actionSet = NUpdateArchive::kUpdateActionSet;
+ break;
+ case NCompressDialog::NUpdateMode::kFresh:
+ actionSet = NUpdateArchive::kFreshActionSet;
+ break;
+ case NCompressDialog::NUpdateMode::kSynchronize:
+ actionSet = NUpdateArchive::kSynchronizeActionSet;
+ break;
+ default:
+ throw 1091756;
+ }
+ archiverInfo = dialog.m_ArchiverInfoList[di.ArchiverInfoIndex];
+ callback->PasswordIsDefined = (!di.Password.IsEmpty());
+ if (callback->PasswordIsDefined)
+ callback->Password = di.Password;
+
+ options.MethodMode.Properties.Clear();
+
+ bool is7z = archiverInfo.Name.CompareNoCase(L"7z") == 0;
+ bool methodOverride = IsThereMethodOverride(is7z, di.Options);
+
+ SetOutProperties(
+ options.MethodMode.Properties,
+ is7z,
+ di.Level,
+ !methodOverride,
+ di.Method,
+ di.Dictionary,
+ di.OrderMode, di.Order,
+ di.SolidIsAllowed, di.Solid,
+ di.MultiThreadIsAllowed, di.MultiThread,
+ di.EncryptionMethod,
+ di.EncryptHeadersIsAllowed, di.EncryptHeaders,
+ di.SFXMode);
+
+ ParseAndAddPropertires(options.MethodMode.Properties, di.Options);
+
+ if (di.SFXMode)
+ options.SfxMode = true;
+ options.MethodMode.FilePath = archiverInfo.FilePath;
+ options.MethodMode.ClassID = archiverInfo.ClassID;
+
+ options.ArchivePath.VolExtension = archiverInfo.GetMainExtension();
+ if(di.SFXMode)
+ options.ArchivePath.BaseExtension = kSFXExtension;
+ else
+ options.ArchivePath.BaseExtension = options.ArchivePath.VolExtension;
+ options.ArchivePath.ParseFromPath(di.ArchiveName);
+
+ NWorkDir::CInfo workDirInfo;
+ ReadWorkDirInfo(workDirInfo);
+ options.WorkingDir.Empty();
+ if (workDirInfo.Mode != NWorkDir::NMode::kCurrent)
+ {
+ UString fullPath;
+ NDirectory::MyGetFullPathName(di.ArchiveName, fullPath);
+ options.WorkingDir = GetWorkDir(workDirInfo, fullPath);
+ NFile::NDirectory::CreateComplexDirectory(options.WorkingDir);
+ }
+ return S_OK;
+}
+
+HRESULT UpdateGUI(
+ const NWildcard::CCensor &censor,
+ CUpdateOptions &options,
+ bool showDialog,
+ CUpdateErrorInfo &errorInfo,
+ COpenCallbackGUI *openCallback,
+ CUpdateCallbackGUI *callback)
+{
+ if (showDialog)
+ {
+ RINOK(ShowDialog(censor, options, callback));
+ }
+ if (options.SfxMode && options.SfxModule.IsEmpty())
+ options.SfxModule = kDefaultSfxModule;
+
+ CThreadUpdating tu;
+
+ tu.UpdateCallbackGUI = callback;
+ tu.UpdateCallbackGUI->Init();
+
+ tu.WildcardCensor = &censor;
+ tu.Options = &options;
+ tu.OpenCallback = openCallback;
+ tu.ErrorInfo = &errorInfo;
+
+ CThread thread;
+ if (!thread.Create(CThreadUpdating::MyThreadFunction, &tu))
+ throw 271824;
+ tu.UpdateCallbackGUI->StartProgressDialog(LangString(IDS_PROGRESS_COMPRESSING, 0x02000DC0));
+ return tu.Result;
+}
+
+
diff --git a/CPP/7zip/UI/GUI/UpdateGUI.h b/CPP/7zip/UI/GUI/UpdateGUI.h
new file mode 100755
index 00000000..c5061aca
--- /dev/null
+++ b/CPP/7zip/UI/GUI/UpdateGUI.h
@@ -0,0 +1,20 @@
+// GUI/UpdateGUI.h
+
+#ifndef __UPDATE_GUI_H
+#define __UPDATE_GUI_H
+
+#include "../Common/Update.h"
+#include "OpenCallbackGUI.h"
+#include "UpdateCallbackGUI.h"
+
+#include "../../FileManager/UpdateCallback100.h"
+
+HRESULT UpdateGUI(
+ const NWildcard::CCensor &censor,
+ CUpdateOptions &options,
+ bool showDialog,
+ CUpdateErrorInfo &errorInfo,
+ COpenCallbackGUI *openCallback,
+ CUpdateCallbackGUI *callback);
+
+#endif
diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile
new file mode 100755
index 00000000..bc6af149
--- /dev/null
+++ b/CPP/7zip/UI/GUI/makefile
@@ -0,0 +1,135 @@
+PROG = 7zG.exe
+LIBS = $(LIBS) user32.lib advapi32.lib oleaut32.lib shell32.lib comctl32.lib htmlhelp.lib ole32.lib comdlg32.lib
+CFLAGS = $(CFLAGS) -I ../../../ -DLANG -DCOMPRESS_MT -DWIN_LONG_PATH
+
+GUI_OBJS = \
+ $O\CompressDialog.obj \
+ $O\ExtractDialog.obj \
+ $O\ExtractGUI.obj \
+ $O\GUI.obj \
+ $O\OpenCallbackGUI.obj \
+ $O\UpdateCallbackGUI.obj \
+ $O\UpdateGUI.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\CommandLineParser.obj \
+ $O\IntToString.obj \
+ $O\Lang.obj \
+ $O\ListFileUtils.obj \
+ $O\NewHandler.obj \
+ $O\StdInStream.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\TextConfig.obj \
+ $O\UTFConvert.obj \
+ $O\Vector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\CommonDialog.obj \
+ $O\DLL.obj \
+ $O\Error.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileName.obj \
+ $O\MemoryLock.obj \
+ $O\PropVariant.obj \
+ $O\PropVariantConversions.obj \
+ $O\Registry.obj \
+ $O\ResourceString.obj \
+ $O\Shell.obj \
+ $O\Synchronization.obj \
+ $O\Window.obj \
+
+WIN_CTRL_OBJS = \
+ $O\ComboBox.obj \
+ $O\Dialog.obj \
+ $O\ListView.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\FilePathAutoRename.obj \
+ $O\FileStreams.obj \
+ $O\StreamUtils.obj \
+
+UI_COMMON_OBJS = \
+ $O\ArchiveCommandLine.obj \
+ $O\ArchiveExtractCallback.obj \
+ $O\ArchiveOpenCallback.obj \
+ $O\ArchiverInfo.obj \
+ $O\DefaultName.obj \
+ $O\EnumDirItems.obj \
+ $O\Extract.obj \
+ $O\ExtractingFilePath.obj \
+ $O\OpenArchive.obj \
+ $O\PropIDUtils.obj \
+ $O\SetProperties.obj \
+ $O\SortUtils.obj \
+ $O\TempFiles.obj \
+ $O\Update.obj \
+ $O\UpdateAction.obj \
+ $O\UpdateCallback.obj \
+ $O\UpdatePair.obj \
+ $O\UpdateProduce.obj \
+ $O\WorkDir.obj \
+ $O\ZipRegistry.obj \
+
+FM_OBJS = \
+ $O\ExtractCallback.obj \
+ $O\FormatUtils.obj \
+ $O\HelpUtils.obj \
+ $O\LangUtils.obj \
+ $O\OpenCallback.obj \
+ $O\ProgramLocation.obj \
+ $O\RegistryUtils.obj \
+ $O\SplitUtils.obj \
+ $O\StringUtils.obj \
+ $O\UpdateCallback100.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(GUI_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(WIN_CTRL_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(UI_COMMON_OBJS) \
+ $(FM_OBJS)\
+ $O\MyMessages.obj \
+ $O\MessagesDialog.obj \
+ $O\OverwriteDialog.obj \
+ $O\PasswordDialog.obj \
+ $O\ProgressDialog.obj \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(GUI_OBJS): $(*B).cpp
+ $(COMPL)
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+ $(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+ $(COMPL)
+$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp
+ $(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+ $(COMPL)
+$(UI_COMMON_OBJS): ../Common/$(*B).cpp
+ $(COMPL)
+$(FM_OBJS): ../../FileManager/$(*B).cpp
+ $(COMPL)
+$O\MyMessages.obj: ../Explorer/MyMessages.cpp
+ $(COMPL)
+$O\MessagesDialog.obj: ../../FileManager/Resource/MessagesDialog/$(*B).cpp
+ $(COMPL)
+$O\OverwriteDialog.obj: ../../FileManager/Resource/OverwriteDialog./$(*B).cpp
+ $(COMPL)
+$O\PasswordDialog.obj: ../../FileManager/Resource/PasswordDialog/$(*B).cpp
+ $(COMPL)
+$O\ProgressDialog.obj: ../../FileManager/Resource/ProgressDialog2/$(*B).cpp
+ $(COMPL)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/UI/GUI/resource.h b/CPP/7zip/UI/GUI/resource.h
new file mode 100755
index 00000000..d88af787
--- /dev/null
+++ b/CPP/7zip/UI/GUI/resource.h
@@ -0,0 +1,45 @@
+#define IDS_CONTEXT_EXTRACT 42
+#define IDS_CONTEXT_EXTRACT_HELP 43
+#define IDS_CONTEXT_COMPRESS 44
+#define IDS_CONTEXT_COMPRESS_HELP 45
+#define IDS_CONTEXT_OPEN 46
+#define IDS_CONTEXT_OPEN_HELP 47
+#define IDS_CONTEXT_TEST 48
+#define IDS_CONTEXT_TEST_HELP 49
+#define IDS_CONTEXT_CAPTION_HELP 50
+#define IDS_CONTEXT_POPUP_CAPTION 51
+#define IDS_OPEN_TYPE_ALL_FILES 80
+
+#define IDS_METHOD_STORE 81
+#define IDS_METHOD_NORMAL 82
+#define IDS_METHOD_MAXIMUM 83
+#define IDS_METHOD_FAST 84
+#define IDS_METHOD_FASTEST 85
+#define IDS_METHOD_ULTRA 86
+
+#define IDS_COMPRESS_UPDATE_MODE_ADD 90
+#define IDS_COMPRESS_UPDATE_MODE_UPDATE 91
+#define IDS_COMPRESS_UPDATE_MODE_FRESH 92
+#define IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE 93
+
+#define IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE 94
+#define IDS_COMPRESS_INCORRECT_VOLUME_SIZE 95
+
+#define IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE 96
+#define IDS_CANT_UPDATE_ARCHIVE 97
+
+#define IDS_PROGRESS_COMPRESSING 98
+#define IDS_PROGRESS_TESTING 99
+#define IDS_ERROR 100
+#define IDS_MESSAGE_NO_ERRORS 101
+#define IDS_CONFIG_DIALOG_CAPTION 102
+
+#define IDS_PASSWORD_USE_ASCII 110
+#define IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH 111
+#define IDS_PASSWORD_IS_TOO_LONG 112
+
+#define IDD_DIALOG_EXTRACT 137
+#define IDB_DELETE 149
+#define IDC_LIST1 1067
+#define IDC_COLUMN_EDIT_WIDTH 1068
+
diff --git a/CPP/7zip/UI/GUI/resource.rc b/CPP/7zip/UI/GUI/resource.rc
new file mode 100755
index 00000000..19f7e61b
--- /dev/null
+++ b/CPP/7zip/UI/GUI/resource.rc
@@ -0,0 +1,57 @@
+#include "../../MyVersionInfo.rc"
+#include <winnt.h>
+#include "resource.h"
+
+MY_VERSION_INFO_APP("7-Zip GUI", "7zg")
+
+IDI_ICON1 ICON "FM.ico"
+
+1 24 MOVEABLE PURE "7zG.exe.manifest"
+
+STRINGTABLE
+BEGIN
+ IDS_CONTEXT_EXTRACT "Extract files..."
+ IDS_CONTEXT_EXTRACT_HELP "Extracts files from the selected archive."
+ IDS_CONTEXT_COMPRESS "Add to archive..."
+ IDS_CONTEXT_COMPRESS_HELP "Adds the selected items to archive."
+ IDS_CONTEXT_OPEN "Open"
+ IDS_CONTEXT_OPEN_HELP "Opens the selected archive."
+ IDS_CONTEXT_TEST "Test archive"
+ IDS_CONTEXT_TEST_HELP "Tests integrity of the selected archive."
+ IDS_CONTEXT_CAPTION_HELP "7-Zip commands"
+ IDS_CONTEXT_POPUP_CAPTION "7-Zip"
+ IDS_OPEN_TYPE_ALL_FILES "All Files"
+ IDS_METHOD_STORE "Store"
+ IDS_METHOD_NORMAL "Normal"
+ IDS_METHOD_MAXIMUM "Maximum"
+ IDS_METHOD_FAST "Fast"
+ IDS_METHOD_FASTEST "Fastest"
+ IDS_METHOD_ULTRA "Ultra"
+ IDS_COMPRESS_UPDATE_MODE_ADD "Add and replace files"
+ IDS_COMPRESS_UPDATE_MODE_UPDATE "Update and add files"
+ IDS_COMPRESS_UPDATE_MODE_FRESH "Freshen existing files"
+ IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE "Synchronize files"
+ IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE "Browse"
+ IDS_COMPRESS_INCORRECT_VOLUME_SIZE "Incorrect volume size"
+ IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE "Specified volume size: {0} bytes.\nAre you sure you want to split archive into such volumes?"
+
+ IDS_PASSWORD_USE_ASCII "Use only English letters, numbers and special characters (!, #, $, ...) for password."
+ IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH "Passwords do not match"
+ IDS_PASSWORD_IS_TOO_LONG "Password is too long"
+
+ IDS_CANT_UPDATE_ARCHIVE "Can not update archive '{0}'"
+ IDS_PROGRESS_COMPRESSING "Compressing"
+ IDS_PROGRESS_TESTING "Testing"
+ IDS_ERROR "Error"
+ IDS_MESSAGE_NO_ERRORS "There are no errors"
+ IDS_CONFIG_DIALOG_CAPTION "7-Zip Options"
+END
+
+#include "../../FileManager/Resource/PropertyName/resource.rc"
+#include "../../FileManager/Resource/OverwriteDialog/resource.rc"
+#include "../../FileManager/Resource/PasswordDialog/resource.rc"
+#include "../../FileManager/Resource/MessagesDialog/resource.rc"
+#include "../../FileManager/Resource/ProgressDialog2/resource.rc"
+#include "../Resource/Extract/resource.rc"
+#include "../Resource/ExtractDialog/resource.rc"
+#include "../Resource/CompressDialog/resource.rc"
diff --git a/CPP/7zip/UI/Resource/CompressDialog/resource.h b/CPP/7zip/UI/Resource/CompressDialog/resource.h
new file mode 100755
index 00000000..847bb3f9
--- /dev/null
+++ b/CPP/7zip/UI/Resource/CompressDialog/resource.h
@@ -0,0 +1,40 @@
+#define IDD_DIALOG_COMPRESS 152
+#define IDC_STATIC_COMPRESS_MEMORY 1022
+#define IDC_STATIC_COMPRESS_MEMORY_DE 1023
+#define IDC_STATIC_COMPRESS_MEMORY_VALUE 1027
+#define IDC_STATIC_COMPRESS_MEMORY_DE_VALUE 1028
+#define IDC_COMPRESS_COMBO_ARCHIVE 1072
+#define IDC_COMPRESS_BUTTON_SET_ARCHIVE 1073
+#define IDC_COMPRESS_COMBO_LEVEL 1074
+#define IDC_COMPRESS_COMBO_UPDATE_MODE 1075
+#define IDC_COMPRESS_COMBO_FORMAT 1076
+#define IDC_COMPRESS_COMBO_VOLUME 1077
+#define IDC_COMPRESS_COMBO_METHOD 1078
+#define IDC_COMPRESS_COMBO_DICTIONARY 1079
+#define IDC_COMPRESS_COMBO_ORDER 1080
+#define IDC_COMPRESS_SFX 1090
+#define IDC_COMPRESS_EDIT_PARAMETERS 1091
+#define IDC_COMPRESS_SOLID 1092
+#define IDC_COMPRESS_MULTI_THREAD 1093
+#define IDC_STATIC_COMPRESS_ARCHIVE 1097
+#define IDC_STATIC_COMPRESS_FORMAT 1098
+#define IDC_STATIC_COMPRESS_LEVEL 1099
+#define IDC_STATIC_COMPRESS_PARAMETERS 1100
+#define IDC_STATIC_COMPRESS_UPDATE_MODE 1101
+#define IDC_STATIC_COMPRESS_OPTIONS 1102
+#define IDC_STATIC_COMPRESS_VOLUME 1103
+#define IDC_STATIC_COMPRESS_METHOD 1104
+#define IDC_STATIC_COMPRESS_DICTIONARY 1105
+#define IDC_STATIC_COMPRESS_ORDER 1106
+
+#define IDC_COMPRESS_ENCRYPTION 1110
+#define IDC_STATIC_COMPRESS_PASSWORD1 1111
+#define IDC_COMPRESS_EDIT_PASSWORD1 1112
+#define IDC_STATIC_COMPRESS_PASSWORD2 1113
+#define IDC_COMPRESS_EDIT_PASSWORD2 1114
+#define IDC_COMPRESS_CHECK_SHOW_PASSWORD 1115
+
+#define IDC_STATIC_COMPRESS_ENCRYPTION_METHOD 1120
+#define IDC_COMPRESS_COMBO_ENCRYPTION_METHOD 1121
+
+#define IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES 1122
diff --git a/CPP/7zip/UI/Resource/CompressDialog/resource.rc b/CPP/7zip/UI/Resource/CompressDialog/resource.rc
new file mode 100755
index 00000000..9019a1af
--- /dev/null
+++ b/CPP/7zip/UI/Resource/CompressDialog/resource.rc
@@ -0,0 +1,117 @@
+#include "resource.h"
+#include "../../../GuiCommon.rc"
+
+#define xSize2 344
+#define ySize2 295
+
+#define xSize (xSize2 + marg + marg)
+#define ySize (ySize2 + marg + marg)
+
+#undef gSize
+#undef gSpace
+#undef g0XSize
+#undef g1XPos
+#undef g1XSize
+#undef g2XSize
+#undef g3XPos
+#undef g3XSize
+#undef g4XPos
+#undef g4XPos2
+#undef g4XSize
+#undef g4XSize2
+#undef bXPos1
+#undef bXPos2
+#undef bXPos3
+#undef bYPos
+
+#define gSize 160
+#define gSpace 24
+
+#define g0XSize 82
+#define g1XPos (marg + g0XSize)
+#define g1XSize (gSize - g0XSize)
+
+#define g2XSize 122
+#define g3XPos (marg + g2XSize)
+#define g3XSize (gSize - g2XSize)
+
+#define g4XPos (marg + gSize + gSpace)
+#define g4XPos2 (g4XPos + 7)
+#define g4XSize (xSize2 - gSize - gSpace)
+#define g4XSize2 (g4XSize - 14)
+
+#define bXPos1 (xSize - marg - bXSize)
+#define bXPos2 (bXPos1 - 10 - bXSize)
+#define bXPos3 (bXPos2 - 10 - bXSize)
+
+#define bYPos (ySize - marg - bYSize)
+
+IDD_DIALOG_COMPRESS DIALOG 0, 0, xSize, ySize MY_MODAL_DIALOG_STYLE
+CAPTION "Add to Archive"
+MY_FONT
+BEGIN
+ LTEXT "&Archive:", IDC_STATIC_COMPRESS_ARCHIVE, marg, marg, xSize2, 8
+ COMBOBOX IDC_COMPRESS_COMBO_ARCHIVE, marg, 18, xSize2 - bDotsSize - 12, 126, CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "...", IDC_COMPRESS_BUTTON_SET_ARCHIVE, xSize - marg - bDotsSize, 17, bDotsSize, bYSize, WS_GROUP
+
+ LTEXT "Archive &format:", IDC_STATIC_COMPRESS_FORMAT, marg, 41, g0XSize, 8
+ COMBOBOX IDC_COMPRESS_COMBO_FORMAT, g1XPos, 39, g1XSize , 80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+
+ LTEXT "Compression &level:",IDC_STATIC_COMPRESS_LEVEL, marg, 62, g0XSize, 8
+ COMBOBOX IDC_COMPRESS_COMBO_LEVEL, g1XPos, 60, g1XSize, 80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+
+ LTEXT "Compression &method:",IDC_STATIC_COMPRESS_METHOD, marg, 83, g0XSize, 8
+ COMBOBOX IDC_COMPRESS_COMBO_METHOD, g1XPos, 81, g1XSize, 80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+
+ LTEXT "&Dictionary size:",IDC_STATIC_COMPRESS_DICTIONARY, marg, 104, g0XSize, 8
+ COMBOBOX IDC_COMPRESS_COMBO_DICTIONARY, g1XPos, 102, g1XSize, 167, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+
+ LTEXT "&Word size:",IDC_STATIC_COMPRESS_ORDER, marg, 125, g0XSize, 8
+ COMBOBOX IDC_COMPRESS_COMBO_ORDER, g1XPos, 123, g1XSize, 141, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+
+
+ LTEXT "Memory usage for Compressing:", IDC_STATIC_COMPRESS_MEMORY, marg, 149, g2XSize, 8
+ RTEXT "0", IDC_STATIC_COMPRESS_MEMORY_VALUE, g3XPos, 149, g3XSize, 8
+
+ LTEXT "Memory usage for Decompressing:", IDC_STATIC_COMPRESS_MEMORY_DE, marg, 163, g2XSize, 8
+ RTEXT "0",IDC_STATIC_COMPRESS_MEMORY_DE_VALUE, g3XPos, 163, g3XSize, 8
+
+
+ CONTROL "Create &Solid archive", IDC_COMPRESS_SOLID,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
+ marg, 181, gSize, 10
+ CONTROL "Multi-threading", IDC_COMPRESS_MULTI_THREAD, "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
+ marg, 195, gSize, 10
+
+ LTEXT "Split to &volumes, bytes:", IDC_STATIC_COMPRESS_VOLUME, marg, 215, gSize, 8
+ COMBOBOX IDC_COMPRESS_COMBO_VOLUME, marg, 227, gSize, 73, CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+
+ LTEXT "&Parameters:",IDC_STATIC_COMPRESS_PARAMETERS, marg, 250, xSize2, 8
+ EDITTEXT IDC_COMPRESS_EDIT_PARAMETERS, marg, 262, xSize2, 14, ES_AUTOHSCROLL
+
+ LTEXT "&Update mode:",IDC_STATIC_COMPRESS_UPDATE_MODE, g4XPos, 39, g4XSize, 8
+ COMBOBOX IDC_COMPRESS_COMBO_UPDATE_MODE, g4XPos, 51, g4XSize, 80, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+
+ GROUPBOX "Options",IDC_STATIC_COMPRESS_OPTIONS, g4XPos, 73, g4XSize, 32
+ CONTROL "Create SF&X archive",IDC_COMPRESS_SFX, "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
+ g4XPos2, 87, g4XSize2, 10
+
+ GROUPBOX "Encryption",IDC_COMPRESS_ENCRYPTION, g4XPos, 113, g4XSize, 127
+
+ LTEXT "Enter password:",IDC_STATIC_COMPRESS_PASSWORD1, g4XPos2, 127, g4XSize2, 8
+ EDITTEXT IDC_COMPRESS_EDIT_PASSWORD1, g4XPos2, 139, g4XSize2, 14, ES_PASSWORD | ES_AUTOHSCROLL
+ LTEXT "Reenter password:",IDC_STATIC_COMPRESS_PASSWORD2, g4XPos2, 159, g4XSize2, 8
+ EDITTEXT IDC_COMPRESS_EDIT_PASSWORD2, g4XPos2, 171, g4XSize2, 14, ES_PASSWORD | ES_AUTOHSCROLL
+
+ CONTROL "Show Password",IDC_COMPRESS_CHECK_SHOW_PASSWORD,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
+ g4XPos2, 192, g4XSize2, 10
+
+ LTEXT "&Encryption method:",IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, g4XPos2, 208, 80, 8
+ COMBOBOX IDC_COMPRESS_COMBO_ENCRYPTION_METHOD, g4XPos2 + 90, 206, g4XSize2 - 90, 198, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+
+ CONTROL "Encrypt file &names", IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
+ g4XPos2, 224, g4XSize2, 10
+
+ DEFPUSHBUTTON "OK", IDOK, bXPos3, bYPos, bXSize, bYSize, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, bXPos2, bYPos, bXSize, bYSize
+ PUSHBUTTON "Help", IDHELP, bXPos1, bYPos, bXSize, bYSize
+END
diff --git a/CPP/7zip/UI/Resource/Extract/resource.h b/CPP/7zip/UI/Resource/Extract/resource.h
new file mode 100755
index 00000000..917c0a34
--- /dev/null
+++ b/CPP/7zip/UI/Resource/Extract/resource.h
@@ -0,0 +1,15 @@
+#define IDS_CANNOT_CREATE_FOLDER 200
+#define IDS_OPEN_IS_NOT_SUPORTED_ARCHIVE 201
+
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC 202
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR 203
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD 204
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED 205
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED 206
+
+#define IDS_EXTRACT_SET_FOLDER 207
+#define IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CANNOT_OPEN_FILE 208
+#define IDS_PROGRESS_EXTRACTING 209
+
+#define IDS_CANT_OPEN_ARCHIVE 103
+#define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 104
diff --git a/CPP/7zip/UI/Resource/Extract/resource.rc b/CPP/7zip/UI/Resource/Extract/resource.rc
new file mode 100755
index 00000000..d3fd1df9
--- /dev/null
+++ b/CPP/7zip/UI/Resource/Extract/resource.rc
@@ -0,0 +1,19 @@
+#include "resource.h"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'"
+ IDS_OPEN_IS_NOT_SUPORTED_ARCHIVE "File is not supported archive."
+ IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC "CRC failed in '{0}'. File is broken."
+ IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR "Data error in '{0}'. File is broken"
+ IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED "CRC failed in encrypted file '{0}'. Wrong password?"
+ IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED "Data error in encrypted file '{0}'. Wrong password?"
+ IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD "Unsupported compression method for '{0}'."
+ IDS_EXTRACT_SET_FOLDER "Specify a location for extracted files."
+ IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CANNOT_OPEN_FILE "Can not open output file '{0}'."
+ IDS_PROGRESS_EXTRACTING "Extracting"
+ IDS_CANT_OPEN_ARCHIVE "Can not open file '{0}' as archive"
+ IDS_CANT_OPEN_ENCRYPTED_ARCHIVE "Can not open encrypted archive '{0}'. Wrong password?"
+END
diff --git a/CPP/7zip/UI/Resource/ExtractDialog/resource.h b/CPP/7zip/UI/Resource/ExtractDialog/resource.h
new file mode 100755
index 00000000..338a2561
--- /dev/null
+++ b/CPP/7zip/UI/Resource/ExtractDialog/resource.h
@@ -0,0 +1,26 @@
+#define IDC_STATIC_EXTRACT_EXTRACT_TO 1020
+#define IDC_EXTRACT_COMBO_PATH 1021
+#define IDC_EXTRACT_BUTTON_SET_PATH 1022
+
+
+#define IDC_EXTRACT_PATH_MODE 1040
+#define IDC_EXTRACT_RADIO_FULL_PATHNAMES 1041
+#define IDC_EXTRACT_RADIO_CURRENT_PATHNAMES 1042
+#define IDC_EXTRACT_RADIO_NO_PATHNAMES 1043
+
+#define IDC_EXTRACT_OVERWRITE_MODE 1050
+#define IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE 1051
+#define IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT 1052
+#define IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES 1053
+#define IDC_EXTRACT_RADIO_SELECTED_FILES 1054
+#define IDC_EXTRACT_RADIO_ALL_FILES 1055
+#define IDC_EXTRACT_RADIO_AUTO_RENAME 1056
+#define IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING 1057
+
+
+#define IDC_EXTRACT_FILES 1060
+
+#define IDC_EXTRACT_PASSWORD 1100
+#define IDC_EXTRACT_EDIT_PASSWORD 1101
+#define IDC_EXTRACT_CHECK_SHOW_PASSWORD 1102
+
diff --git a/CPP/7zip/UI/Resource/ExtractDialog/resource.rc b/CPP/7zip/UI/Resource/ExtractDialog/resource.rc
new file mode 100755
index 00000000..05cf5ea6
--- /dev/null
+++ b/CPP/7zip/UI/Resource/ExtractDialog/resource.rc
@@ -0,0 +1,80 @@
+#include "resource.h"
+#include "../../../GuiCommon.rc"
+
+#define xSize2 285
+#define ySize2 204
+
+#define xSize (xSize2 + marg + marg)
+#define ySize (ySize2 + marg + marg)
+
+#undef g1XSize
+#undef g1XSize2
+#undef g1XPos2
+#undef g2XPos
+#undef g2XPos2
+#undef g2XSize
+#undef g2XSize2
+
+#define bYPos (ySize - marg - bYSize)
+
+#define g1XSize 127
+#define g1XSize2 (g1XSize - 13)
+#define g1XPos2 (marg + 7)
+
+#define gSpace 14
+#define g2XPos (marg + g1XSize + gSpace)
+#define g2XPos2 (g2XPos + 7)
+#define g2XSize (xSize2 - g1XSize - gSpace)
+#define g2XSize2 (g2XSize - 14)
+
+#define bXPos1 (xSize - marg - bXSize)
+#define bXPos2 (bXPos1 - 10 - bXSize)
+#define bXPos3 (bXPos2 - 10 - bXSize)
+
+IDD_DIALOG_EXTRACT DIALOG DISCARDABLE 0, 0, xSize, ySize MY_MODAL_DIALOG_STYLE
+CAPTION "Extract"
+MY_FONT
+BEGIN
+ LTEXT "E&xtract to:", IDC_STATIC_EXTRACT_EXTRACT_TO, marg, marg, xSize2, 8
+
+ COMBOBOX IDC_EXTRACT_COMBO_PATH, marg, 21, xSize2 - bDotsSize - 13, 126, CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+
+ PUSHBUTTON "...", IDC_EXTRACT_BUTTON_SET_PATH, xSize - marg - bDotsSize, 20, bDotsSize, bYSize, WS_GROUP
+
+ GROUPBOX "Path mode",IDC_EXTRACT_PATH_MODE, marg, 44, g1XSize, 57
+ CONTROL "Full pathnames", IDC_EXTRACT_RADIO_FULL_PATHNAMES,"Button", BS_AUTORADIOBUTTON | WS_GROUP,
+ g1XPos2, 57, g1XSize2, 10
+ CONTROL "Current pathnames",IDC_EXTRACT_RADIO_CURRENT_PATHNAMES, "Button", BS_AUTORADIOBUTTON,
+ g1XPos2, 71, g1XSize2, 10
+ CONTROL "No pathnames", IDC_EXTRACT_RADIO_NO_PATHNAMES, "Button", BS_AUTORADIOBUTTON,
+ g1XPos2, 85, g1XSize2, 10
+
+ GROUPBOX "Overwrite mode",IDC_EXTRACT_OVERWRITE_MODE, g2XPos, 44, g2XSize, 88, WS_GROUP
+ CONTROL "Ask before overwrite", IDC_EXTRACT_RADIO_ASK_BEFORE_OVERWRITE, "Button", BS_AUTORADIOBUTTON | WS_GROUP,
+ g2XPos2, 57, g2XSize2, 10
+ CONTROL "Overwrite without prompt", IDC_EXTRACT_RADIO_OVERWRITE_WITHOUT_PROMPT, "Button", BS_AUTORADIOBUTTON,
+ g2XPos2, 71, g2XSize2, 10
+ CONTROL "Skip existing files", IDC_EXTRACT_RADIO_SKIP_EXISTING_FILES, "Button", BS_AUTORADIOBUTTON,
+ g2XPos2, 85, g2XSize2, 10
+ CONTROL "Auto rename", IDC_EXTRACT_RADIO_AUTO_RENAME, "Button", BS_AUTORADIOBUTTON,
+ g2XPos2, 99, g2XSize2, 10
+ CONTROL "Auto rename existing files", IDC_EXTRACT_RADIO_AUTO_RENAME_EXISTING, "Button", BS_AUTORADIOBUTTON,
+ g2XPos2,113, g2XSize2, 10
+
+ GROUPBOX "Files",IDC_EXTRACT_FILES, marg, 140, 127, 48, NOT WS_VISIBLE | WS_DISABLED | WS_GROUP
+ CONTROL "&Selected files",IDC_EXTRACT_RADIO_SELECTED_FILES, "Button", BS_AUTORADIOBUTTON | NOT WS_VISIBLE | WS_DISABLED | WS_GROUP,
+ g1XPos2, 153, g1XSize2, 10
+ CONTROL "&All files",IDC_EXTRACT_RADIO_ALL_FILES, "Button", BS_AUTORADIOBUTTON | NOT WS_VISIBLE | WS_DISABLED,
+ g1XPos2, 166, g1XSize2, 10
+
+ GROUPBOX "Password",IDC_EXTRACT_PASSWORD, g2XPos, 142, g2XSize, 46
+ EDITTEXT IDC_EXTRACT_EDIT_PASSWORD,154,153,130,14, ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "Show Password",IDC_EXTRACT_CHECK_SHOW_PASSWORD,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
+ g2XPos2, 172, g2XSize2, 10
+
+ DEFPUSHBUTTON "OK", IDOK, bXPos3, bYPos, bXSize, bYSize, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, bXPos2, bYPos, bXSize, bYSize
+ PUSHBUTTON "Help", IDHELP, bXPos1, bYPos, bXSize, bYSize
+END
+
+
diff --git a/CPP/7zip/UI/makefile b/CPP/7zip/UI/makefile
new file mode 100755
index 00000000..942beaa0
--- /dev/null
+++ b/CPP/7zip/UI/makefile
@@ -0,0 +1,10 @@
+DIRS = \
+ Client7z\~ \
+ Console\~ \
+ Explorer\~ \
+ GUI\~ \
+
+all: $(DIRS)
+
+$(DIRS):
+!include "../SubBuild.mak"