diff --git a/7zTypes.h b/7zTypes.h index 65b3af6..35dd4b3 100644 --- a/7zTypes.h +++ b/7zTypes.h @@ -60,7 +60,7 @@ typedef int WRes; #ifndef RINOK -#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#define RINOK(x) if (int __result__ = (x); __result__ != 0) return __result__ #endif typedef unsigned char Byte; diff --git a/Handler.cpp b/Handler.cpp index e1b6d90..5a31579 100644 --- a/Handler.cpp +++ b/Handler.cpp @@ -33,7 +33,6 @@ class CHandler : CMyComPtr basePak; CObjectVector> paks; UInt64 size = 0; - bool missingPak = false; }; STDMETHODIMP CHandler::Open( IInStream* inStream, const UInt64* maxCheckStartPosition, IArchiveOpenCallback* callback ) MY_NO_THROW_DECL_ONLY @@ -60,16 +59,16 @@ STDMETHODIMP CHandler::Open( IInStream* inStream, const UInt64* maxCheckStartPos if ( largestId != -1 ) { CMyComPtr volCallback; - callback->QueryInterface( IID_IArchiveOpenVolumeCallback, (void**)&volCallback ); + RINOK( callback->QueryInterface( IID_IArchiveOpenVolumeCallback, (void**)&volCallback ) ); if ( !volCallback ) - return S_OK; + return E_FAIL; UString name; { NWindows::NCOM::CPropVariant prop; RINOK( volCallback->GetProperty( kpidName, &prop ) ); if ( prop.vt != VT_BSTR ) - return S_OK; + return E_FAIL; name = prop.bstrVal; } @@ -85,8 +84,8 @@ STDMETHODIMP CHandler::Open( IInStream* inStream, const UInt64* maxCheckStartPos swprintf_s( base, L"%s%03d.vpk", name.GetBuf(), i ); IInStream* s; - if ( volCallback->GetStream( base, &s ) == S_FALSE || s == nullptr ) - missingPak = true; + if ( volCallback->GetStream( base, &s ) != S_OK || s == nullptr ) + return ERROR_FILE_NOT_FOUND; paks.Add( s ); } } @@ -225,31 +224,26 @@ STDMETHODIMP CHandler::Extract( const UInt32* indices, UInt32 numItems, Int32 te totalSize += f[indices[i]].second.fileLength; } - extractCallback->SetTotal( totalSize ); - - CLocalProgress* lps = new CLocalProgress; - CMyComPtr progress = lps; - lps->Init( extractCallback, false ); + RINOK( extractCallback->SetTotal( totalSize ) ); - NCompress::CCopyCoder* copyCoderSpec = new NCompress::CCopyCoder(); - CMyComPtr copyCoder = copyCoderSpec; + CMyComPtr progress = new CLocalProgress; + progress->Init( extractCallback, false ); - CLimitedSequentialOutStream* outStreamSpec = new CLimitedSequentialOutStream; - CMyComPtr outStream( outStreamSpec ); + CMyComPtr copyCoder = new NCompress::CCopyCoder; + CMyComPtr outStream = new CLimitedSequentialOutStream; + const Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; UInt64 currentTotalSize = 0; for ( UInt32 i = 0; i < numItems; i++ ) { - lps->InSize = lps->OutSize = currentTotalSize; - RINOK( lps->SetCur() ); + progress->InSize = progress->OutSize = currentTotalSize; + RINOK( progress->SetCur() ); CMyComPtr realOutStream; - Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; UInt32 index = allFilesMode ? i : indices[i]; RINOK( extractCallback->GetStream( index, &realOutStream, askMode ) ); const auto& item = f[index].second; - currentTotalSize += item.fileLength; if ( !testMode && !realOutStream ) @@ -264,9 +258,9 @@ STDMETHODIMP CHandler::Extract( const UInt32* indices, UInt32 numItems, Int32 te } RINOK( extractCallback->PrepareOperation( askMode ) ); - outStreamSpec->SetStream( realOutStream ); + outStream->SetStream( realOutStream ); realOutStream.Release(); - outStreamSpec->Init( item.fileLength ); + outStream->Init( item.fileLength ); Int32 opRes; CMyComPtr inStream; HRESULT res = GetStream( index, &inStream ); @@ -277,9 +271,9 @@ STDMETHODIMP CHandler::Extract( const UInt32* indices, UInt32 numItems, Int32 te else { RINOK( copyCoder->Code( inStream, outStream, NULL, NULL, progress ) ); - opRes = outStreamSpec->IsFinishedOK() ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kDataError; + opRes = outStream->IsFinishedOK() ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kDataError; } - outStreamSpec->ReleaseStream(); + outStream->ReleaseStream(); RINOK( extractCallback->SetOperationResult( opRes ) ); } return S_OK; @@ -303,19 +297,18 @@ STDMETHODIMP CHandler::GetStream( UInt32 index, ISequentialInStream** stream ) if ( i.preloadLength == 0 ) return CreateLimitedInStream( i.archiveIdx == 0x7FFF ? basePak : paks[i.archiveIdx], offset, i.fileLength, stream ); - CLimitedCachedInStream* limitedStreamSpec = new CLimitedCachedInStream; - CMyComPtr limitedStream = limitedStreamSpec; - limitedStreamSpec->SetStream( i.archiveIdx == 0x7FFF ? basePak : paks[i.archiveIdx], offset ); + CMyComPtr limitedStream = new CLimitedCachedInStream; + limitedStream->SetStream( i.archiveIdx == 0x7FFF ? basePak : paks[i.archiveIdx], offset ); - auto& preload = limitedStreamSpec->Buffer; + auto& preload = limitedStream->Buffer; preload.Alloc( i.preloadLength ); size_t size = i.preloadLength; - basePak->Seek( i.preloadOffset, STREAM_SEEK_SET, nullptr ); - ReadStream( basePak, preload, &size ); + RINOK( basePak->Seek( i.preloadOffset, STREAM_SEEK_SET, nullptr ) ); + RINOK( ReadStream( basePak, preload, &size ) ); - limitedStreamSpec->SetCache( i.preloadLength, 0 ); - limitedStreamSpec->InitAndSeek( 0, i.fileLength ); + limitedStream->SetCache( i.preloadLength, 0 ); + RINOK( limitedStream->InitAndSeek( 0, i.fileLength ) ); *stream = limitedStream.Detach(); return S_OK; } @@ -753,21 +746,21 @@ class VpkWriter return S_OK; } - void write_pak( ISequentialOutStream* outStream, IArchiveUpdateCallback* callback ) + HRESULT write_pak( ISequentialOutStream* outStream, IArchiveUpdateCallback* callback ) { CLocalProgress* lps = new CLocalProgress; CMyComPtr progress = lps; lps->Init( callback, true ); - NCompress::CCopyCoder* copyCoderSpec = new NCompress::CCopyCoder(); - CMyComPtr copyCoder = copyCoderSpec; + CMyComPtr copyCoder = new NCompress::CCopyCoder; CMyComPtr stream_; - outStream->QueryInterface( IID_IOutStream, (void**)&stream_ ); + RINOK( outStream->QueryInterface( IID_IOutStream, (void**)&stream_ ) ); CCacheOutStream* stream = new CCacheOutStream(); - stream->Allocate(); - stream->Init( outStream, stream_ ); + if ( !stream->Allocate() ) + return E_OUTOFMEMORY; + RINOK( stream->Init( outStream, stream_ ) ); UInt32 size = 0, treeSize = 0; FilesByExt sorted_files; @@ -777,38 +770,38 @@ class VpkWriter treeSize += static_cast( dirs.size() + 1 ); // add null after each all files in each directory + null after last dir ++treeSize; // null after last ext - write_header( stream, size, treeSize ); + RINOK( write_header( stream, size, treeSize ) ); UInt32 currentOffset = 0; for ( auto& [ext, dirs] : sorted_files ) { - write( stream, ext ); + RINOK( write( stream, ext ) ); for ( auto& [dir, files] : dirs ) { - write( stream, dir ); + RINOK( write( stream, dir ) ); for ( auto& [file, data] : files ) { UInt64 pos; - stream->Seek( 0, STREAM_SEEK_CUR, &pos ); + RINOK( stream->Seek( 0, STREAM_SEEK_CUR, &pos ) ); lps->InSize = lps->OutSize = pos; - lps->SetCur(); - write( stream, file ); - write( stream, calc_crc( *data ) ); - write( stream, 0 ); - write( stream, 0x7FFF ); - write( stream, currentOffset ); - write( stream, data->size ); - write( stream, 0xFFFF ); + RINOK( lps->SetCur() ); + RINOK( write( stream, file ) ); + RINOK( write( stream, calc_crc( *data ) ) ); + RINOK( write( stream, 0 ) ); + RINOK( write( stream, 0x7FFF ) ); + RINOK( write( stream, currentOffset ) ); + RINOK( write( stream, data->size ) ); + RINOK( write( stream, 0xFFFF ) ); currentOffset += data->size; } - write( stream, {} ); + RINOK( write( stream, {} ) ); } - write( stream, {} ); + RINOK( write( stream, {} ) ); } - write( stream, {} ); + RINOK( write( stream, {} ) ); - stream->Seek( treeSize + sizeof( libvpk::meta::VPKHeader ), STREAM_SEEK_SET, nullptr ); + RINOK( stream->Seek( treeSize + sizeof( libvpk::meta::VPKHeader ), STREAM_SEEK_SET, nullptr ) ); for ( auto& [ext, dirs] : sorted_files ) { @@ -817,33 +810,35 @@ class VpkWriter for ( auto& [file, data] : files ) { UInt64 pos; - stream->Seek( 0, STREAM_SEEK_CUR, &pos ); + RINOK( stream->Seek( 0, STREAM_SEEK_CUR, &pos ) ); lps->InSize = lps->OutSize = pos; - lps->SetCur(); - copyCoder->Code( data->stream, stream, NULL, NULL, progress ); + RINOK( lps->SetCur() ); + RINOK( copyCoder->Code( data->stream, stream, NULL, NULL, progress ) ); data->stream->Release(); } } } - stream->FlushCache(); + RINOK( stream->FlushCache() ); stream->Release(); + + return S_OK; } private: template - void write( IOutStream* stream, const T& data ) + HRESULT write( IOutStream* stream, const T& data ) { - stream->Write( &data, sizeof( T ), nullptr ); + return stream->Write( &data, sizeof( T ), nullptr ); } template <> - void write( IOutStream* stream, const std::string& string ) + HRESULT write( IOutStream* stream, const std::string& string ) { - stream->Write( string.c_str(), static_cast( string.size() + 1 ), nullptr ); + return stream->Write( string.c_str(), static_cast( string.size() + 1 ), nullptr ); } - static void write_header( IOutStream* stream, UInt32 size, UInt32 treeSize ) + static HRESULT write_header( IOutStream* stream, UInt32 size, UInt32 treeSize ) { libvpk::meta::VPKHeader header; header.signature = libvpk::meta::VPKHeader::ValidSignature; @@ -851,7 +846,7 @@ class VpkWriter header.treeSize = static_cast( treeSize ); header.fileDataSectionSize = static_cast( size ); - stream->Write( &header, sizeof( header ), nullptr ); + return stream->Write( &header, sizeof( header ), nullptr ); } struct Dir @@ -970,19 +965,19 @@ STDMETHODIMP CHandler::UpdateItems( ISequentialOutStream* outStream, UInt32 numI UInt64 size = prop.uhVal.QuadPart; CMyComPtr fileInStream; - callback->GetStream( i, &fileInStream ); + RINOK( callback->GetStream( i, &fileInStream ) ); if ( !fileInStream ) return E_FAIL; IInStream* inStream; - fileInStream->QueryInterface( IID_IInStream, (void**)&inStream ); + RINOK( fileInStream->QueryInterface( IID_IInStream, (void**)&inStream ) ); if ( !inStream ) return E_FAIL; RINOK( writer.addItem( UnicodeStringToMultiByte( name ), static_cast( size ), inStream ) ); } - writer.write_pak( outStream, callback ); + RINOK( writer.write_pak( outStream, callback ) ); RINOK( callback->SetOperationResult( NArchive::NExtract::NOperationResult::kOK ) ); diff --git a/libvpk++.h b/libvpk++.h index 3af4871..b1ea712 100644 --- a/libvpk++.h +++ b/libvpk++.h @@ -88,20 +88,24 @@ namespace libvpk HRESULT open( IInStream* stream, IArchiveOpenCallback* callback ) { + UInt64 pos; + RINOK( stream->Seek( 0, STREAM_SEEK_CUR, &pos ) ); auto initialHeader = helpers::read( stream ); if ( initialHeader.signature != meta::VPKHeader1::ValidSignature ) - return E_FAIL; + return S_FALSE; if ( initialHeader.version == 1 ) m_header = initialHeader; else if ( initialHeader.version == 2 ) { // Return to the beginning and read a full VPK 2 ptr. - stream->Seek( 0, STREAM_SEEK_SET, nullptr ); + RINOK( stream->Seek( pos, STREAM_SEEK_SET, nullptr ) ); m_header = helpers::read( stream ); + if ( m_header.signature != meta::VPKHeader1::ValidSignature ) + return S_FALSE; } else - return E_FAIL; + return S_FALSE; const UInt64 total = m_header.treeSize; callback->SetTotal( nullptr, &total ); @@ -145,8 +149,8 @@ namespace libvpk { UInt64 pos; const UInt64 files = m_files.size(); - stream->Seek( 0, STREAM_SEEK_CUR, &pos ); - callback->SetCompleted( &files, &pos ); + RINOK( stream->Seek( 0, STREAM_SEEK_CUR, &pos ) ); + RINOK( callback->SetCompleted( &files, &pos ) ); } auto name = helpers::read( stream ); @@ -181,16 +185,16 @@ namespace libvpk // Read the terminator for the file info. if ( helpers::read( stream ) != 0xFFFF ) - return E_FAIL; + return S_FALSE; UInt64 pos; - stream->Seek( 0, STREAM_SEEK_CUR, &pos ); + RINOK( stream->Seek( 0, STREAM_SEEK_CUR, &pos ) ); VPKFileDesc desc{ archiveIndex, preloadBytes, static_cast( pos ), offset, length, crc }; // Skip over the preload section if ( desc.preloadLength != 0 ) { - stream->Seek( desc.preloadLength, STREAM_SEEK_CUR, nullptr ); + RINOK( stream->Seek( desc.preloadLength, STREAM_SEEK_CUR, nullptr ) ); desc.fileLength += desc.preloadLength; }