--- /dev/null
+/*/Merge7z453.cpp\r
+\r
+Copyright (c) Jochen Neubeck\r
+\r
+This library is free software; you can redistribute it and/or\r
+modify it under the terms of the GNU Lesser General Public\r
+License as published by the Free Software Foundation; either\r
+version 2.1 of the License, or (at your option) any later version.\r
+\r
+This library is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+Lesser General Public License for more details.\r
+\r
+You should have received a copy of the GNU Lesser General Public\r
+License along with this library; if not, write to the Free Software\r
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\r
+\r
+Please mind 2. b) of the GNU LGPL terms, and log your changes below.\r
+\r
+DATE: BY: DESCRIPTION:\r
+========== ================== ================================================\r
+2009-09-26 Jochen Neubeck Branched from Merge7z459.cpp\r
+2010-04-24 Jochen Neubeck Fix compression\r
+*/\r
+\r
+#include "stdafx.h"\r
+\r
+#define INITGUID\r
+#include <initguid.h>\r
+\r
+#include "Merge7zCommon.h"\r
+\r
+#include "7zip/UI/FileManager/OpenCallback.h"\r
+#include "7zip/UI/FileManager/ExtractCallback.h"\r
+\r
+#include "7zip/UI/Common/ArchiveExtractCallback.h"\r
+#include "7zip/UI/GUI/UpdateCallbackGUI.h"\r
+\r
+#include "Windows/Thread.h"\r
+\r
+/**\r
+ * @brief Extraction thread\r
+ */\r
+class CThreadExtracting : public CProgressThreadVirt\r
+{\r
+protected:\r
+ virtual HRESULT ProcessVirt()\r
+ {\r
+ HRESULT result = Archive->Extract(indices, numItems, false, ArchiveExtractCallback);\r
+ return result;\r
+ }\r
+ CExtractCallbackImp *ExtractCallbackSpec;\r
+ IInArchive *Archive;\r
+ IArchiveExtractCallback *ArchiveExtractCallback;\r
+ const UINT32 *indices;\r
+ UINT32 numItems;\r
+public:\r
+ //HRESULT result;\r
+\r
+ CThreadExtracting\r
+ (\r
+ CExtractCallbackImp *ExtractCallbackSpec,\r
+ IInArchive *Archive,\r
+ IArchiveExtractCallback *ArchiveExtractCallback,\r
+ const CSysString &title,\r
+ HWND hwndParent,\r
+ const UINT32 *indices = 0,\r
+ UINT32 numItems = -1\r
+ ):\r
+ ExtractCallbackSpec(ExtractCallbackSpec),\r
+ Archive(Archive),\r
+ ArchiveExtractCallback(ArchiveExtractCallback),\r
+ indices(indices),\r
+ numItems(numItems)\r
+ {\r
+ ExtractCallbackSpec->ProgressDialog = &ProgressDialog;\r
+ ProgressDialog.CompressingMode = false;\r
+ //result = E_FAIL;\r
+ if (HRESULT hr = Create(GetUnicodeString(title), hwndParent))\r
+ {\r
+ Complain(hr, NULL);\r
+ }\r
+ }\r
+};\r
+\r
+/**\r
+ * @brief Initialize Inspector\r
+ */\r
+Format7zDLL::Interface::Inspector::Inspector(Format7zDLL::Interface *format, LPCTSTR path)\r
+: format(format), archive(0), file(0), callback(0), path(path), ustrDefaultName(GetUnicodeString(path))\r
+{\r
+}\r
+\r
+/**\r
+ * @brief Initialize Inspector\r
+ */\r
+void Format7zDLL::Interface::Inspector::Init(HWND hwndParent)\r
+{\r
+ format->GetDefaultName(hwndParent, ustrDefaultName);\r
+ COpenArchiveCallback *callbackImpl = new COpenArchiveCallback;\r
+ //COpenCallbackImp *callbackImpl = new COpenCallbackImp;\r
+ (archive = format->GetInArchive()) -> AddRef();\r
+ (file = new CInFileStream) -> AddRef();\r
+ (callback = callbackImpl) -> AddRef();\r
+ callbackImpl->PasswordIsDefined = false;\r
+ callbackImpl->ParentWindow = hwndParent;\r
+ /*CMyComBSTR password;\r
+ callback->CryptoGetTextPassword(&password);*/\r
+ if COMPLAIN(!NFile::NFind::CFindFile().FindFirst(path, fileInfo))\r
+ {\r
+ Complain(ERROR_FILE_NOT_FOUND, path);\r
+ }\r
+ if COMPLAIN(!file->Open(path))\r
+ {\r
+ Complain(ERROR_OPEN_FAILED, path);\r
+ }\r
+ if COMPLAIN(archive->Open(file, 0, callback) != S_OK)\r
+ {\r
+ Complain(ERROR_CANT_ACCESS_FILE, path);\r
+ }\r
+ passwordIsDefined = callbackImpl->PasswordIsDefined;\r
+ password = callbackImpl->Password;\r
+}\r
+\r
+/**\r
+ * @brief Extract set of items specified by index\r
+ */\r
+HRESULT Format7zDLL::Interface::Inspector::Extract(HWND hwndParent, LPCTSTR folder, const UINT32 *indices, UINT32 numItems)\r
+{\r
+ CArchiveExtractCallback *extractCallbackSpec = 0;\r
+ CExtractCallbackImp *extractCallbackSpec2 = 0;\r
+ HRESULT result = 0;\r
+ try\r
+ {\r
+ if (*folder)\r
+ {\r
+ if COMPLAIN(!NFile::NDirectory::CreateComplexDirectory(folder))\r
+ {\r
+ Complain(ERROR_CANNOT_MAKE, folder);\r
+ }\r
+ }\r
+\r
+ (extractCallbackSpec2 = new CExtractCallbackImp) -> AddRef();\r
+\r
+ extractCallbackSpec2->Init();\r
+\r
+ extractCallbackSpec2->OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;\r
+ extractCallbackSpec2->PasswordIsDefined = passwordIsDefined;\r
+ extractCallbackSpec2->Password = password;\r
+\r
+ (extractCallbackSpec = new CArchiveExtractCallback) -> AddRef();\r
+\r
+ extractCallbackSpec->InitForMulti\r
+ (\r
+ false,\r
+ NExtract::NPathMode::kFullPathnames,\r
+ NExtract::NOverwriteMode::kWithoutPrompt\r
+ );\r
+ CArc arc;\r
+ arc.Archive = archive;\r
+ arc.Path = GetUnicodeString(path);\r
+ arc.DefaultName = ustrDefaultName;\r
+ arc.FormatIndex = 0;\r
+ arc.SubfileIndex = 0;\r
+ extractCallbackSpec->Init\r
+ (\r
+ NULL,\r
+ &arc,\r
+ extractCallbackSpec2,\r
+ false, //stdOutMode\r
+ false, //testMode\r
+ false, //crcMode\r
+ GetUnicodeString(folder),\r
+ UStringVector(),\r
+ (UInt64)(Int64)-1\r
+ );\r
+\r
+ result = CThreadExtracting\r
+ (\r
+ extractCallbackSpec2,\r
+ archive,\r
+ extractCallbackSpec,\r
+ PathFindFileName(path),\r
+ hwndParent,\r
+ indices,\r
+ numItems\r
+ ).Result;\r
+\r
+ //.result;\r
+\r
+ /*if COMPLAIN(extractCallbackSpec->_numErrors)\r
+ {\r
+ // There is no canned system message for this one, so it won't\r
+ // localize. I can't help it.\r
+ Complain(_T("%s:\n%I64u error(s)"), path, extractCallbackSpec->_numErrors);\r
+ }*/\r
+ if COMPLAIN(result != S_OK && result != E_ABORT)\r
+ {\r
+ Complain(result, path);\r
+ }\r
+ }\r
+ catch (Complain *complain)\r
+ {\r
+ result = complain->Alert(hwndParent);\r
+ }\r
+ Release(static_cast<IArchiveExtractCallback*>(extractCallbackSpec));\r
+ Release(static_cast<IFolderArchiveExtractCallback*>(extractCallbackSpec2));\r
+ return result;\r
+}\r
+\r
+/**\r
+ * @brief Compression thread\r
+ */\r
+class CThreadUpdating : public CProgressThreadVirt\r
+{\r
+protected:\r
+ virtual HRESULT ProcessVirt()\r
+ {\r
+ HRESULT result = outArchive->UpdateItems(file, numItems, updateCallbackSpec);\r
+ return result;\r
+ }\r
+ CUpdateCallbackGUI *updateCallbackGUI;\r
+ IOutArchive *outArchive;\r
+ CArchiveUpdateCallback *updateCallbackSpec;\r
+ COutFileStream *file;\r
+public:\r
+ HRESULT result;\r
+ UINT32 numItems;\r
+ CThreadUpdating\r
+ (\r
+ CUpdateCallbackGUI *updateCallbackGUI,\r
+ IOutArchive *outArchive,\r
+ CArchiveUpdateCallback *updateCallbackSpec,\r
+ UINT32 numItems,\r
+ COutFileStream *file,\r
+ const CSysString &title,\r
+ HWND hwndParent\r
+ ):\r
+ updateCallbackGUI(updateCallbackGUI),\r
+ outArchive(outArchive),\r
+ updateCallbackSpec(updateCallbackSpec),\r
+ numItems(numItems),\r
+ file(file)\r
+ {\r
+ result = E_FAIL;\r
+ updateCallbackGUI->ProgressDialog = &ProgressDialog;\r
+ if (HRESULT hr = Create(GetUnicodeString(title), hwndParent))\r
+ {\r
+ Complain(hr, NULL);\r
+ }\r
+ }\r
+};\r
+\r
+/**\r
+ * @brief Construct Updater\r
+ */\r
+Format7zDLL::Interface::Updater::Updater(Format7zDLL::Interface *format, LPCTSTR path)\r
+: format(format), outArchive(0), file(0), path(path)\r
+{\r
+}\r
+\r
+/**\r
+ * @brief Initialize Updater\r
+ */\r
+void Format7zDLL::Interface::Updater::Init(HWND hwndParent)\r
+{\r
+ (outArchive = format->GetOutArchive()) -> AddRef();\r
+ (file = new COutFileStream) -> AddRef();\r
+ if COMPLAIN(!file->Create(path, true))\r
+ {\r
+ Complain(ERROR_CANNOT_MAKE, path);\r
+ }\r
+}\r
+\r
+/**\r
+ * @brief Commit update\r
+ */\r
+HRESULT Format7zDLL::Interface::Updater::Commit(HWND hwndParent)\r
+{\r
+ CArchiveUpdateCallback *updateCallbackSpec = 0;\r
+ CUpdateCallbackGUI *updateCallbackGUI = 0;\r
+ HRESULT result = 0;\r
+ try\r
+ {\r
+ // Ref counts are not always accurate with 7-Zip.\r
+ // An extra AddRef() ensures that interfaces remain valid until they\r
+ // are explicitly released at the end of this function.\r
+ (updateCallbackSpec = new CArchiveUpdateCallback) -> AddRef();\r
+ (updateCallbackGUI = new CUpdateCallbackGUI);// -> AddRef();\r
+\r
+ updateCallbackGUI->Init();\r
+\r
+ // No items in dest archive. We always recreate the dest archive\r
+ // Build the operationChain. One element per item\r
+ CRecordVector<CUpdatePair2> operationChain;\r
+ CUpdatePair2 pair2;\r
+ pair2.NewData = pair2.NewProps = true;\r
+\r
+ operationChain.Reserve(dirItems.Items.Size());\r
+ //\r
+ int i;\r
+ for (i = 0 ; i < dirItems.Items.Size() ; i++)\r
+ {\r
+ pair2.DirIndex = i;\r
+ operationChain.Add(pair2);\r
+ }\r
+ operationChain.ReserveDown();\r
+\r
+ /* The following code may or may not help implement update on existing\r
+ /* archives, which is currently not supported.\r
+ UINT32 fileTimeType;\r
+ outArchive->GetFileTimeType(&fileTimeType);\r
+\r
+ CObjectVector<CUpdatePair> updatePairs;\r
+ GetUpdatePairInfoList(dirItems, archiveItems, NFileTimeType::EEnum(fileTimeType), updatePairs); // must be done only once!!!\r
+ \r
+ CObjectVector<CUpdatePair2> operationChain;\r
+ UpdateProduce(dirItems, archiveItems, updatePairs, NUpdateArchive::kAddActionSet, operationChain);*/\r
+\r
+ // Now compress...\r
+ updateCallbackSpec->DirItems = &dirItems;\r
+ updateCallbackSpec->ArcItems = &archiveItems;\r
+ updateCallbackSpec->UpdatePairs = &operationChain;\r
+ updateCallbackSpec->Callback = updateCallbackGUI;\r
+\r
+ result = CThreadUpdating\r
+ (\r
+ updateCallbackGUI,\r
+ outArchive,\r
+ updateCallbackSpec,\r
+ operationChain.Size(),\r
+ file,\r
+ PathFindFileName(path),\r
+ hwndParent\r
+ ).Result;\r
+\r
+ if COMPLAIN(result != S_OK && result != E_ABORT)\r
+ {\r
+ Complain(result, path);\r
+ }\r
+ }\r
+ catch (Complain *complain)\r
+ {\r
+ result = complain->Alert(hwndParent);\r
+ }\r
+ // Always release interfaces in this order, or else all hell will break\r
+ // loose!\r
+ Release(static_cast<IArchiveUpdateCallback*>(updateCallbackSpec));\r
+ delete updateCallbackGUI;\r
+ return result;\r
+}\r