// GZipUpdate.cpp #include "StdAfx.h" #include "GZipUpdate.h" #include "Common/Defs.h" #include "Common/StringConvert.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../ICoder.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/Copy/CopyCoder.h" #include "../Common/InStreamWithCRC.h" #ifdef COMPRESS_DEFLATE #include "../../Compress/Deflate/DeflateEncoder.h" #else // {23170F69-40C1-278B-0401-080000000100} DEFINE_GUID(CLSID_CCompressDeflateEncoder, 0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00); #include "../Common/CoderLoader.h" extern CSysString GetDeflateCodecPath(); #endif namespace NArchive { namespace NGZip { static const Byte kHostOS = NFileHeader::NHostOS::kFAT; HRESULT UpdateArchive(IInStream * /* inStream */, UInt64 unpackSize, ISequentialOutStream *outStream, const CItem &newItem, const CCompressionMethodMode &compressionMethod, int indexInClient, IArchiveUpdateCallback *updateCallback) { UInt64 complexity = 0; complexity += unpackSize; RINOK(updateCallback->SetTotal(complexity)); #ifndef COMPRESS_DEFLATE CCoderLibrary lib; #endif CMyComPtr deflateEncoder; complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CMyComPtr fileInStream; RINOK(updateCallback->GetStream(indexInClient, &fileInStream)); CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC; CMyComPtr crcStream(inStreamSpec); inStreamSpec->SetStream(fileInStream); inStreamSpec->Init(); CLocalProgress *localProgressSpec = new CLocalProgress; CMyComPtr localProgress = localProgressSpec; localProgressSpec->Init(updateCallback, true); CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo; CMyComPtr compressProgress = localCompressProgressSpec; COutArchive outArchive; outArchive.Create(outStream); CItem item = newItem; item.CompressionMethod = NFileHeader::NCompressionMethod::kDeflate; item.ExtraFlags = 0; item.HostOS = kHostOS; RINOK(outArchive.WriteHeader(item)); localCompressProgressSpec->Init(localProgress, &complexity, NULL); { #ifdef COMPRESS_DEFLATE deflateEncoder = new NCompress::NDeflate::NEncoder::CCOMCoder; #else RINOK(lib.LoadAndCreateCoder(GetDeflateCodecPath(), CLSID_CCompressDeflateEncoder, &deflateEncoder)); #endif NWindows::NCOM::CPropVariant properties[] = { compressionMethod.NumPasses, compressionMethod.NumFastBytes, compressionMethod.NumMatchFinderCycles }; PROPID propIDs[] = { NCoderPropID::kNumPasses, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinderCycles }; int numProps = sizeof(propIDs) / sizeof(propIDs[0]); if (!compressionMethod.NumMatchFinderCyclesDefined) numProps--; CMyComPtr setCoderProperties; RINOK(deflateEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, numProps)); } RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, compressProgress)); item.FileCRC = inStreamSpec->GetCRC(); item.UnPackSize32 = (UInt32)inStreamSpec->GetSize(); RINOK(outArchive.WritePostHeader(item)); return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); } }}