VOID PkUpdateArchiveExtractCallback::Run() { HRESULT result; IInArchive *currentArchive; PhAcquireQueuedLockExclusive(&Lock); while (!ThreadStopping) { if (!InArchive) { PhWaitForCondition(&Condition, &Lock, NULL); continue; } currentArchive = InArchive; currentArchive->AddRef(); result = currentArchive->Extract(NULL, -1, FALSE, this); currentArchive->Release(); if (result != E_ABORT && !SUCCEEDED(result)) Result = result; } PhReleaseQueuedLockExclusive(&Lock); }
HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *realIndices) { _hardLinks.Clear(); if (!_arc->Ask_INode) return S_OK; IInArchive *archive = _arc->Archive; CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs; { UInt32 numItems; if (realIndices) numItems = realIndices->Size(); else { RINOK(archive->GetNumberOfItems(&numItems)); } for (UInt32 i = 0; i < numItems; i++) { CHardLinkNode h; bool defined; UInt32 realIndex = realIndices ? (*realIndices)[i] : i; RINOK(Archive_Get_HardLinkNode(archive, realIndex, h, defined)); if (defined) { bool isAltStream = false; RINOK(Archive_IsItem_AltStream(archive, realIndex, isAltStream)); if (!isAltStream) hardIDs.Add(h); } } } hardIDs.Sort2(); { // wee keep only items that have 2 or more items unsigned k = 0; unsigned numSame = 1; for (unsigned i = 1; i < hardIDs.Size(); i++) { if (hardIDs[i].Compare(hardIDs[i - 1]) != 0) numSame = 1; else if (++numSame == 2) { if (i - 1 != k) hardIDs[k] = hardIDs[i - 1]; k++; } } hardIDs.DeleteFrom(k); } _hardLinks.PrepareLinks(); return S_OK; }
int ArchiveFile::ExtractItem(int index, const char* outFilename) const { assert(!s_formatInfos.empty()); //assert(index >= 0 && index < m_numItems); if(!(index >= 0 && index < m_numItems)) return 0; ArchiveItem& item = m_items[index]; int rv = item.size; #ifndef ANDROID DWORD outAttributes = GetFileAttributes(outFilename); if(outAttributes & FILE_ATTRIBUTE_READONLY) SetFileAttributes(outFilename, outAttributes & ~FILE_ATTRIBUTE_READONLY); // temporarily remove read-only attribute so we can decompress to there #endif if(m_typeIndex < 0) { #ifndef ANDROID //I don't *think* we care about this // uncompressed if(!CopyFile(m_filename, outFilename, false)) #endif rv = 0; } else { IInArchive* object = NULL; HRESULT hr = E_FAIL; if(SUCCEEDED(CreateObject(&s_formatInfos[m_typeIndex].guid, &IID_IInArchive, (void**)&object))) { InFileStream* ifs = new InFileStream(m_filename); if(SUCCEEDED(object->Open(ifs,0,0))) { gameInfo.resize(rv); OutStream* os = new OutStream(index, outFilename); const UInt32 indices [1] = {index}; hr = object->Extract(indices, 1, 0, os); object->Close(); } object->Release(); } if(FAILED(hr)) rv = 0; } #ifndef ANDROID if(outAttributes & FILE_ATTRIBUTE_READONLY) SetFileAttributes(outFilename, outAttributes); // restore read-only attribute #endif return rv; }
HRESULT PkUpdatePackage( __in PPK_FILE_STREAM FileStream, __in PPK_PACKAGE Package, __in PPK_ACTION_LIST ActionList, __in PPK_PACKAGE_CALLBACK Callback, __in_opt PVOID Context ) { HRESULT result; IInArchive *inArchive; PkFileStream *fileStream; IOutArchive *outArchive; PkArchiveUpdateCallback *updateCallback; inArchive = (IInArchive *)Package; fileStream = (PkFileStream *)FileStream; result = inArchive->QueryInterface(IID_IOutArchive_I, (void **)&outArchive); if (!SUCCEEDED(result)) return result; updateCallback = new PkArchiveUpdateCallback; updateCallback->ReferenceCount = 1; updateCallback->ActionList = ActionList; updateCallback->Callback = Callback; updateCallback->Context = Context; updateCallback->InArchive = inArchive; updateCallback->CreateActionMap(); result = outArchive->UpdateItems(&fileStream->OutStream, ActionList->NumberOfActions, updateCallback); if (SUCCEEDED(result)) result = PkpCloseExtractCallback(updateCallback); else PkpCloseExtractCallback(updateCallback); updateCallback->Release(); outArchive->Release(); return result; }
int ArchiveFile::ExtractItem(int index, unsigned char* outBuffer, int bufSize) const { assert(!s_formatInfos.empty()); //assert(index >= 0 && index < m_numItems); if(!(index >= 0 && index < m_numItems)) return 0; ArchiveItem& item = m_items[index]; if(bufSize < item.size) return 0; if(m_typeIndex < 0) { // uncompressed FILE* file = fopen(m_filename, "rb"); fread(outBuffer, 1, item.size, file); fclose(file); } else { IInArchive* object = NULL; HRESULT hr = E_FAIL; if(SUCCEEDED(CreateObject(&s_formatInfos[m_typeIndex].guid, &IID_IInArchive, (void**)&object))) { InFileStream* ifs = new InFileStream(m_filename); if(SUCCEEDED(object->Open(ifs,0,0))) { OutStream* os = new OutStream(index, outBuffer, item.size); const UInt32 indices [1] = {index}; hr = object->Extract(indices, 1, 0, os); object->Close(); } object->Release(); } if(FAILED(hr)) return 0; } return item.size; }
HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) { // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) { Files.Free(); Dirs.Clear(); Dirs.AddNew(); IInArchive *archive = arc.Archive; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); if (progress) RINOK(progress->SetTotal(numItems)); Files.Alloc(numItems); UString path; UString name; NCOM::CPropVariant prop; for (UInt32 i = 0; i < numItems; i++) { if (progress && (i & 0xFFFF) == 0) { UInt64 currentItemIndex = i; RINOK(progress->SetCompleted(¤tItemIndex)); } const wchar_t *s = NULL; unsigned len = 0; bool isPtrName = false; #ifdef MY_CPU_LE if (arc.GetRawProps) { const void *p; UInt32 size; UInt32 propType; if (arc.GetRawProps->GetRawProp(i, kpidPath, &p, &size, &propType) == S_OK && propType == NPropDataType::kUtf16z && size > 2) { // is (size <= 2), it's empty name, and we call default arc.GetItemPath(); len = size / 2 - 1; s = (const wchar_t *)p; isPtrName = true; } } if (!s) #endif { prop.Clear(); RINOK(arc.Archive->GetProperty(i, kpidPath, &prop)); if (prop.vt == VT_BSTR) { s = prop.bstrVal; len = ::SysStringLen(prop.bstrVal); } else if (prop.vt != VT_EMPTY) return E_FAIL; if (len == 0) { RINOK(arc.GetDefaultItemPath(i, path)); len = path.Len(); s = path; } /* RINOK(arc.GetItemPath(i, path)); len = path.Len(); s = path; */ } unsigned curItem = 0; /* if (arc.Ask_Deleted) { bool isDeleted = false; RINOK(Archive_IsItem_Deleted(archive, i, isDeleted)); if (isDeleted) curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]"); } */ unsigned namePos = 0; for (unsigned j = 0; j < len; j++) { wchar_t c = s[j]; if (c == WCHAR_PATH_SEPARATOR || c == L'/') { name.SetFrom(s + namePos, j - namePos); curItem = AddDir(curItem, -1, name); namePos = j + 1; } } /* that code must be implemeted to hide alt streams in list. if (arc.Ask_AltStreams) { bool isAltStream; RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)); if (isAltStream) { } } */ bool isDir; RINOK(Archive_IsItem_Dir(archive, i, isDir)); CProxyFile &f = Files[i]; f.NameLen = len - namePos; s += namePos; if (isPtrName) f.Name = s; else { f.Name = new wchar_t[f.NameLen + 1]; f.NeedDeleteName = true; MyStringCopy((wchar_t *)f.Name, s); } if (isDir) { name = s; AddDir(curItem, (int)i, name); } else Dirs[curItem].SubFiles.Add(i); } CalculateSizes(0, archive); // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s); return S_OK; }
HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, bool stdInMode, UStringVector &arcPaths, UStringVector &arcPathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; int numArcs = /* stdInMode ? 1 : */ arcPaths.Size(); for (int i = 0; i < numArcs; i++) { const UString &archiveName = arcPaths[i]; UInt64 arcPackSize = 0; if (!stdInMode) { NFile::NFind::CFileInfoW fi; if (!fi.Find(archiveName) || fi.IsDir()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } arcPackSize = fi.Size; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; g_StdOut << endl << "Error: " << archiveName << ": "; if (result == S_FALSE) { #ifndef _NO_CRYPTO if (openCallback.Open_WasPasswordAsked()) g_StdOut << "Can not open encrypted archive. Wrong password?"; else #endif g_StdOut << "Can not open file as archive"; } else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else g_StdOut << NError::MyFormatMessage(result); g_StdOut << endl; numErrors++; continue; } if (!stdInMode) for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { arcPaths.Delete(index); arcPathsFull.Delete(index); numArcs = arcPaths.Size(); } } if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; for (int i = 0; i < archiveLink.Arcs.Size(); i++) { const CArc &arc = archiveLink.Arcs[i]; g_StdOut << "--\n"; PrintPropPair(L"Path", arc.Path); PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name); if (!arc.ErrorMessage.IsEmpty()) PrintPropPair(L"Error", arc.ErrorMessage); UInt32 numProps; IInArchive *archive = arc.Archive; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 j = 0; j < numProps; j++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt)); NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(propID, &prop)); UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) PrintPropPair(GetPropName(propID, name), s); } } if (i != archiveLink.Arcs.Size() - 1) { UInt32 numProps; g_StdOut << "----\n"; if (archive->GetNumberOfProperties(&numProps) == S_OK) { UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex; for (UInt32 j = 0; j < numProps; j++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt)); NCOM::CPropVariant prop; RINOK(archive->GetProperty(mainIndex, propID, &prop)); UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) PrintPropPair(GetPropName(propID, name), s); } } } } g_StdOut << endl; if (techMode) g_StdOut << "----------\n"; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } const CArc &arc = archiveLink.Arcs.Back(); IInArchive *archive = arc.Archive; if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 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; HRESULT res = arc.GetItemPath(i, filePath); if (stdInMode && res == E_INVALIDARG) break; RINOK(res); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(arc, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (!stdInMode && totalPackSizePointer == 0) { if (archiveLink.VolumePaths.Size() != 0) arcPackSize += archiveLink.VolumesSize; totalPackSize = (numFiles == 0) ? 0 : arcPackSize; totalPackSizePointer = &totalPackSize; } if (totalUnPackSizePointer == 0 && numFiles == 0) { totalUnPackSize = 0; totalUnPackSizePointer = &totalUnPackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && numArcs > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << numArcs << endl; } return S_OK; }
HRESULT __stdcall CArchiveExtractCallback::GetStream ( unsigned int index, ISequentialOutStream **outStream, int askExtractMode ) { CPropVariant value; IInArchive *archive = m_pArchive->m_pArchive; if ( askExtractMode == 0 ) //extract { if ( archive->GetProperty (index, kpidPath, &value) != S_OK ) return S_OK; //!!! to return error char szArcFileName[MAX_PATH]; char szFullName[MAX_PATH]; if ( value.vt == VT_BSTR ) WideCharToMultiByte (CP_OEMCP, 0, value.bstrVal, -1, szArcFileName, MAX_PATH, NULL, NULL); else { //strcpy (szArcFileName, FSF.PointToName (m_pArchive->m_lpFileName)); //CutTo (szArcFileName, '.', true); ATLASSERT(FALSE); } strcpy (szFullName, m_lpDestPath.c_str()); PathAppendA(szFullName, szArcFileName); if ( (int)m_nLastProcessed == -1 ) m_nLastProcessed = 0; FILETIME ftCreationTime, ftLastAccessTime, ftLastWriteTime; DWORD dwFileAttributes = 0; memset (&ftCreationTime, 0, sizeof (FILETIME)); memset (&ftLastAccessTime, 0, sizeof (FILETIME)); memset (&ftLastWriteTime, 0, sizeof (FILETIME)); if ( archive->GetProperty (index, kpidAttrib, &value) == S_OK ) { if ( value.vt == VT_UI4 ) dwFileAttributes = value.ulVal; } if ( archive->GetProperty (index, kpidCTime, &value) == S_OK ) { if ( value.vt == VT_FILETIME ) memcpy (&ftCreationTime, &value.filetime, sizeof (FILETIME)); } if ( archive->GetProperty (index, kpidATime, &value) == S_OK ) { if ( value.vt == VT_FILETIME ) memcpy (&ftLastAccessTime, &value.filetime, sizeof (FILETIME)); } if ( archive->GetProperty (index, kpidMTime, &value) == S_OK ) { if ( value.vt == VT_FILETIME ) memcpy (&ftLastWriteTime, &value.filetime, sizeof (FILETIME)); } bool bIsFolder = false; if ( archive->GetProperty (index, kpidIsDir, &value) == S_OK ) { if (value.vt == VT_BOOL) bIsFolder = (value.boolVal == VARIANT_TRUE); } if ( bIsFolder || dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY ) { *outStream = NULL; CreateDirEx (szFullName, dwFileAttributes); } else { CreateDirs (szFullName); COutFile *file = new COutFile (szFullName); if ( file->Open () ) { file->SetAttributes (dwFileAttributes); file->SetTime (&ftCreationTime, &ftLastAccessTime, &ftLastWriteTime); *outStream = file; m_files.push_back( szFullName ); } else delete file; } } else *outStream = NULL; return S_OK; }
ArchiveFile::ArchiveFile(const char* filename) { assert(!s_formatInfos.empty()); m_typeIndex = -1; m_numItems = 0; m_items = NULL; m_filename = NULL; FILE* file = fopen(filename, "rb"); if(!file) return; m_filename = new char[strlen(filename)+1]; strcpy(m_filename, filename); // detect archive type using format signature in file for(size_t i = 0; i < s_formatInfos.size() && m_typeIndex < 0; i++) { fseek(file, 0, SEEK_SET); std::string& formatSig = s_formatInfos[i].signature; int len = formatSig.size(); if(len == 0) continue; // because some formats have no signature char* fileSig = (char*)_alloca(len); fread(fileSig, 1, len, file); if(!memcmp(formatSig.c_str(), fileSig, len)) m_typeIndex = i; } // if no signature match has been found, detect archive type using filename. // this is only for signature-less formats const char* fileExt = strrchr(filename, '.'); if(fileExt++) { for(size_t i = 0; i < s_formatInfos.size() && m_typeIndex < 0; i++) { if(s_formatInfos[i].signature.empty()) { std::vector<std::string>& formatExts = s_formatInfos[i].extensions; for(size_t j = 0; j < formatExts.size(); j++) { if(!_stricmp(formatExts[j].c_str(), fileExt)) { m_typeIndex = i; break; } } } } } if(m_typeIndex < 0) { // uncompressed m_numItems = 1; m_items = new ArchiveItem[m_numItems]; fseek(file, 0, SEEK_END); m_items[0].size = ftell(file); m_items[0].name = new char[strlen(filename)+1]; strcpy(m_items[0].name, filename); } else { IInArchive* object = NULL; if(SUCCEEDED(CreateObject(&s_formatInfos[m_typeIndex].guid, &IID_IInArchive, (void**)&object))) { InFileStream* ifs = new InFileStream(filename); if(SUCCEEDED(object->Open(ifs,0,0))) { UInt32 numItems = 0; object->GetNumberOfItems(&numItems); m_numItems = numItems; m_items = new ArchiveItem[m_numItems]; for(int i = 0; i < m_numItems; i++) { PROPVARIANT var = {VT_EMPTY}; ArchiveItem& item = m_items[i]; object->GetProperty(i, kpidSize, &var); item.size = var.uhVal.LowPart; object->GetProperty(i, kpidPath, &var); std::string& path = wstrToStr(var.bstrVal); item.name = new char[path.size()+1]; strcpy(item.name, path.c_str()); //object->GetProperty(i, kpidMethod, &var); //std::string& method = wstrToStr(var.bstrVal); //item.method = new char[method.size()+1]; //strcpy(item.method, method.c_str()); object->GetProperty(i, kpidEncrypted, &var); #ifdef _NO_CRYPTO if(var.boolVal) item.size = 0; // don't support decompressing it, pretend size zero #else #error password support NYI... see client7z.cpp item.encrypted = !!var.boolVal; #endif VariantClear((VARIANTARG*)&var); } object->Close(); } object->Release(); } } fclose(file); }
HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress) { RootFolder.Clear(); IInArchive *archive = arc.Archive; { ThereIsPathProp = false; UInt32 numProps; archive->GetNumberOfProperties(&numProps); for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE varType; RINOK(archive->GetPropertyInfo(i, &name, &propID, &varType)); if (propID == kpidPath) { ThereIsPathProp = true; break; } } } UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); if (progress != NULL) { UInt64 totalItems = numItems; RINOK(progress->SetTotal(totalItems)); } UString fileName; for (UInt32 i = 0; i < numItems; i++) { if (progress != NULL && (i & 0xFFFFF) == 0) { UInt64 currentItemIndex = i; RINOK(progress->SetCompleted(¤tItemIndex)); } UString filePath; RINOK(arc.GetItemPath(i, filePath)); CProxyFolder *curItem = &RootFolder; int len = filePath.Length(); fileName.Empty(); for (int j = 0; j < len; j++) { wchar_t c = filePath[j]; if (c == WCHAR_PATH_SEPARATOR || c == L'/') { curItem = curItem->AddDirSubItem((UInt32)(Int32)-1, false, fileName); fileName.Empty(); } else fileName += c; } bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (isFolder) curItem->AddDirSubItem(i, true, fileName); else curItem->AddFileSubItem(i, fileName); } RootFolder.CalculateSizes(archive); return S_OK; }
HRESULT ListArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 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(codecs, 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; UInt32 numProps; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (archive->GetArchiveProperty(propID, &prop) != S_OK) continue; UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) g_StdOut << GetPropName(propID, name) << " = " << s << endl; } } if (techMode) g_StdOut << "----------\n"; if (numProps > 0) g_StdOut << endl; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 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; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && archivePaths.Size() > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << archivePaths.Size() << endl; } return S_OK; }
HRESULT PkArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { HRESULT result; PPK_ACTION action; PK_PARAMETER_GET_STREAM getStream; PkFileStream *fileStream; action = GetAction(index); if (!action) return E_ABORT; if (action->Type == PkAddFromPackageType) { IInArchive *package; PROPVARIANT sizeValue; PkFileStream *pipe; IOutStream *writer; IInStream *reader; package = (IInArchive *)action->u.AddFromPackage.Package; PropVariantInit(&sizeValue); result = package->GetProperty(action->u.AddFromPackage.IndexInPackage, kpidSize, &sizeValue); if (!SUCCEEDED(result)) return result; pipe = new PkFileStream(PkPipeFileStream, NULL, sizeValue.hVal.QuadPart); pipe->InitializePipe(&writer, &reader); pipe->Release(); if (pipe->Buffer) { if (!ExtractCallback) { ExtractCallback = new PkUpdateArchiveExtractCallback(); ExtractCallback->Owner = this; ExtractCallback->StartThread(); } ExtractCallback->SetNewJob(package, action->u.AddFromPackage.IndexInPackage, writer); writer->Release(); *inStream = reader; } else { writer->Release(); reader->Release(); return E_OUTOFMEMORY; } return S_OK; } else if (action->Type == PkUpdateType) { return E_INVALIDARG; } memset(&getStream, 0, sizeof(PK_PARAMETER_GET_STREAM)); if (!SUCCEEDED(result = Callback(PkGetStreamMessage, action, &getStream, Context))) { *inStream = NULL; return result; } if (!getStream.FileStream) { *inStream = NULL; return E_FAIL; } fileStream = (PkFileStream *)getStream.FileStream; *inStream = &fileStream->InStream; return S_OK; }
HRESULT PkArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { PPK_ACTION action; FILE_NETWORK_OPEN_INFORMATION networkOpenInfo; action = GetAction(index); if (!action) return E_ABORT; if (action->Type == PkAddFromPackageType) { HRESULT result; IInArchive *package; package = (IInArchive *)action->u.AddFromPackage.Package; result = package->GetProperty(action->u.AddFromPackage.IndexInPackage, propID, value); if (!SUCCEEDED(result)) return result; return S_OK; } else if (action->Type == PkUpdateType) { return InArchive->GetProperty(action->u.Update.Index, propID, value); } switch (propID) { case kpidPath: value->vt = VT_BSTR; value->bstrVal = SysAllocString(action->u.Add.Destination->Buffer); break; case kpidIsDir: value->vt = VT_BOOL; value->boolVal = !!(action->u.Add.Flags & PK_ACTION_DIRECTORY); break; case kpidSize: networkOpenInfo.EndOfFile.QuadPart = 0; Callback(PkGetSizeMessage, action, &networkOpenInfo, Context); value->vt = VT_UI8; value->uhVal.QuadPart = networkOpenInfo.EndOfFile.QuadPart; break; case kpidAttrib: networkOpenInfo.FileAttributes = 0; Callback(PkGetAttributesMessage, action, &networkOpenInfo, Context); value->vt = VT_UI4; value->uintVal = networkOpenInfo.FileAttributes; break; case kpidCTime: networkOpenInfo.CreationTime.QuadPart = 0; Callback(PkGetCreationTimeMessage, action, &networkOpenInfo, Context); value->vt = VT_FILETIME; value->filetime.dwLowDateTime = networkOpenInfo.CreationTime.LowPart; value->filetime.dwHighDateTime = networkOpenInfo.CreationTime.HighPart; break; case kpidATime: networkOpenInfo.LastAccessTime.QuadPart = 0; Callback(PkGetAccessTimeMessage, action, &networkOpenInfo, Context); value->vt = VT_FILETIME; value->filetime.dwLowDateTime = networkOpenInfo.LastAccessTime.LowPart; value->filetime.dwHighDateTime = networkOpenInfo.LastAccessTime.HighPart; break; case kpidMTime: networkOpenInfo.LastWriteTime.QuadPart = 0; Callback(PkGetModifiedTimeMessage, action, &networkOpenInfo, Context); value->vt = VT_FILETIME; value->filetime.dwLowDateTime = networkOpenInfo.LastWriteTime.LowPart; value->filetime.dwHighDateTime = networkOpenInfo.LastWriteTime.HighPart; break; case kpidIsAnti: value->vt = VT_BOOL; value->boolVal = FALSE; break; } return S_OK; }
HRESULT PkExtractPackage( __in PPK_PACKAGE Package, __in_opt PPK_ACTION_LIST ActionList, __in PPK_PACKAGE_CALLBACK Callback, __in_opt PVOID Context ) { HRESULT result; IInArchive *inArchive; PkArchiveExtractCallback *extractCallback; PULONG items; ULONG numberOfItems; PPK_ACTION_SEGMENT segment; ULONG i; result = S_OK; inArchive = (IInArchive *)Package; extractCallback = new PkArchiveExtractCallback; extractCallback->ReferenceCount = 1; extractCallback->ActionList = ActionList; extractCallback->Callback = Callback; extractCallback->Context = Context; extractCallback->InArchive = inArchive; if (ActionList) { items = (PULONG)PhAllocate(sizeof(ULONG) * ActionList->NumberOfActions); segment = ActionList->FirstSegment; numberOfItems = 0; while (segment) { for (i = 0; i < segment->Count; i++) { if (numberOfItems >= ActionList->NumberOfActions) { result = E_INVALIDARG; break; } if (segment->Actions[i].Type == PkUpdateType) { items[numberOfItems] = segment->Actions[i].u.Update.Index; numberOfItems++; } } segment = segment->Next; } extractCallback->CreateActionMap(); } else { items = NULL; numberOfItems = -1; } if (!SUCCEEDED(result)) return result; result = inArchive->Extract((UInt32 *)items, numberOfItems, FALSE, extractCallback); if (items) PhFree(items); extractCallback->Release(); return result; }
HRESULT PkOpenPackageWithFilter( __in PPK_FILE_STREAM FileStream, __inout_opt PPK_ACTION_LIST ActionList, __in_opt PPK_PACKAGE_CALLBACK Callback, __in_opt PVOID Context, __out PPK_PACKAGE *Package ) { HRESULT result; PkFileStream *fileStream; IInArchive *inArchive; ULONG numberOfItems; ULONG i; fileStream = (PkFileStream *)FileStream; result = PkpCreateSevenZipObject(&SevenZipHandlerGuid, &IID_IInArchive_I, (void **)&inArchive); if (!SUCCEEDED(result)) return result; result = inArchive->Open(&fileStream->InStream, NULL, NULL); if (!SUCCEEDED(result)) { inArchive->Release(); return result; } if (ActionList) { result = inArchive->GetNumberOfItems((UInt32 *)&numberOfItems); if (SUCCEEDED(result)) { if (Callback) { for (i = 0; i < numberOfItems; i++) { PK_PARAMETER_FILTER_ITEM filterItem; PROPVARIANT pathValue; PROPVARIANT attributesValue; PROPVARIANT isDirValue; PropVariantInit(&pathValue); PropVariantInit(&attributesValue); PropVariantInit(&isDirValue); if (SUCCEEDED(inArchive->GetProperty(i, kpidPath, &pathValue)) && pathValue.vt == VT_BSTR && SUCCEEDED(inArchive->GetProperty(i, kpidAttrib, &attributesValue)) && SUCCEEDED(inArchive->GetProperty(i, kpidIsDir, &isDirValue))) { filterItem.Reject = FALSE; filterItem.Path.Length = wcslen(pathValue.bstrVal) * sizeof(WCHAR); filterItem.Path.Buffer = pathValue.bstrVal; filterItem.FileAttributes = attributesValue.uintVal; filterItem.NewContext = NULL; if (isDirValue.boolVal) filterItem.FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; Callback(PkFilterItemMessage, NULL, &filterItem, Context); if (!filterItem.Reject) { PkAppendUpdateToActionList(ActionList, i, filterItem.NewContext); } PropVariantClear(&pathValue); PropVariantClear(&attributesValue); PropVariantClear(&isDirValue); } else { result = E_FAIL; PropVariantClear(&pathValue); PropVariantClear(&attributesValue); PropVariantClear(&isDirValue); break; } } } else { for (i = 0; i < numberOfItems; i++) { PkAppendUpdateToActionList(ActionList, i, NULL); } } } } if (SUCCEEDED(result)) *Package = (PPK_PACKAGE)inArchive; else inArchive->Release(); return result; }
static HRESULT DecompressArchive( const CArc &arc, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, UString &errorMessage, UInt64 &stdInProcessed) { stdInProcessed = 0; IInArchive *archive = arc.Archive; CRecordVector<UInt32> realIndices; if (!options.StdInMode) { UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for (UInt32 i = 0; i < numItems; i++) { UString filePath; RINOK(arc.GetItemPath(i, 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; } } UStringVector removePathParts; UString outDir = options.OutputDir; outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName)); #ifdef _WIN32 // GetCorrectFullFsPath doesn't like "..". // outDir.TrimRight(); // outDir = GetCorrectFullFsPath(outDir); #endif 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( options.StdInMode ? &wildcardCensor : NULL, &arc, callback, options.StdOutMode, options.TestMode, options.CalcCrc, outDir, removePathParts, packSize); #if !defined(_7ZIP_ST) && !defined(_SFX) RINOK(SetProperties(archive, options.Properties)); #endif HRESULT result; Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0; if (options.StdInMode) { result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec); NCOM::CPropVariant prop; if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK) if (prop.vt == VT_UI8 || prop.vt == VT_UI4) stdInProcessed = ConvertPropVariantToUInt64(prop); } else result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec); return callback->ExtractResult(result); }