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); }
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; }
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; }
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 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; }