michael@0: // ArchiverInfo.cpp michael@0: michael@0: #include "StdAfx.h" michael@0: michael@0: #include "ArchiverInfo.h" michael@0: michael@0: #ifndef EXCLUDE_COM michael@0: michael@0: #include "Common/StringConvert.h" michael@0: #include "Windows/FileFind.h" michael@0: #include "Windows/FileName.h" michael@0: #include "Windows/DLL.h" michael@0: #ifdef _WIN32 michael@0: #include "Windows/Registry.h" michael@0: #endif michael@0: #include "Windows/PropVariant.h" michael@0: #include "../../Archive/IArchive.h" michael@0: michael@0: using namespace NWindows; michael@0: using namespace NFile; michael@0: michael@0: #endif michael@0: michael@0: extern HINSTANCE g_hInstance; michael@0: michael@0: #ifndef EXCLUDE_COM michael@0: michael@0: static void SplitString(const UString &srcString, UStringVector &destStrings) michael@0: { michael@0: destStrings.Clear(); michael@0: UString string; michael@0: int len = srcString.Length(); michael@0: if (len == 0) michael@0: return; michael@0: for (int i = 0; i < len; i++) michael@0: { michael@0: wchar_t c = srcString[i]; michael@0: if (c == L' ') michael@0: { michael@0: if (!string.IsEmpty()) michael@0: { michael@0: destStrings.Add(string); michael@0: string.Empty(); michael@0: } michael@0: } michael@0: else michael@0: string += c; michael@0: } michael@0: if (!string.IsEmpty()) michael@0: destStrings.Add(string); michael@0: } michael@0: michael@0: typedef UInt32 (WINAPI * GetHandlerPropertyFunc)( michael@0: PROPID propID, PROPVARIANT *value); michael@0: michael@0: static UString GetModuleFolderPrefix() michael@0: { michael@0: UString path; michael@0: NDLL::MyGetModuleFileName(g_hInstance, path); michael@0: int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR); michael@0: return path.Left(pos + 1); michael@0: } michael@0: michael@0: static wchar_t *kFormatFolderName = L"Formats"; michael@0: michael@0: #ifdef _WIN32 michael@0: static LPCTSTR kRegistryPath = TEXT("Software\\7-zip"); michael@0: static LPCWSTR kProgramPathValue = L"Path"; michael@0: static bool ReadPathFromRegistry(HKEY baseKey, UString &path) michael@0: { michael@0: NRegistry::CKey key; michael@0: if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) michael@0: if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) michael@0: { michael@0: NName::NormalizeDirPathPrefix(path); michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: #endif michael@0: michael@0: static UString GetBaseFolderPrefixFromRegistry() michael@0: { michael@0: UString moduleFolderPrefix = GetModuleFolderPrefix(); michael@0: NFind::CFileInfoW fileInfo; michael@0: if (NFind::FindFile(moduleFolderPrefix + kFormatFolderName, fileInfo)) michael@0: if (fileInfo.IsDirectory()) michael@0: return moduleFolderPrefix; michael@0: UString path; michael@0: #ifdef _WIN32 michael@0: if(ReadPathFromRegistry(HKEY_CURRENT_USER, path)) michael@0: return path; michael@0: if(ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) michael@0: return path; michael@0: #endif michael@0: return moduleFolderPrefix; michael@0: } michael@0: michael@0: typedef UInt32 (WINAPI *CreateObjectPointer)( michael@0: const GUID *clsID, michael@0: const GUID *interfaceID, michael@0: void **outObject); michael@0: michael@0: #endif michael@0: michael@0: #ifndef _SFX michael@0: static void SetBuffer(CByteBuffer &bb, const Byte *data, int size) michael@0: { michael@0: bb.SetCapacity(size); michael@0: memmove((Byte *)bb, data, size); michael@0: } michael@0: #endif michael@0: michael@0: void ReadArchiverInfoList(CObjectVector &archivers) michael@0: { michael@0: archivers.Clear(); michael@0: michael@0: #ifdef EXCLUDE_COM michael@0: michael@0: #ifdef FORMAT_7Z michael@0: { michael@0: CArchiverInfo item; michael@0: item.UpdateEnabled = true; michael@0: item.Name = L"7z"; michael@0: item.Extensions.Add(CArchiverExtInfo(L"7z")); michael@0: #ifndef _SFX michael@0: const unsigned char kSig[] = {'7' , 'z', 0xBC, 0xAF, 0x27, 0x1C}; michael@0: SetBuffer(item.StartSignature, kSig, 6); michael@0: #endif michael@0: archivers.Add(item); michael@0: } michael@0: #endif michael@0: michael@0: #ifdef FORMAT_BZIP2 michael@0: { michael@0: CArchiverInfo item; michael@0: item.UpdateEnabled = true; michael@0: item.KeepName = true; michael@0: item.Name = L"BZip2"; michael@0: item.Extensions.Add(CArchiverExtInfo(L"bz2")); michael@0: item.Extensions.Add(CArchiverExtInfo(L"tbz2", L".tar")); michael@0: #ifndef _SFX michael@0: const unsigned char sig[] = {'B' , 'Z', 'h' }; michael@0: SetBuffer(item.StartSignature, sig, 3); michael@0: #endif michael@0: archivers.Add(item); michael@0: } michael@0: #endif michael@0: michael@0: #ifdef FORMAT_GZIP michael@0: { michael@0: CArchiverInfo item; michael@0: item.UpdateEnabled = true; michael@0: item.Name = L"GZip"; michael@0: item.Extensions.Add(CArchiverExtInfo(L"gz")); michael@0: item.Extensions.Add(CArchiverExtInfo(L"tgz", L".tar")); michael@0: #ifndef _SFX michael@0: const unsigned char sig[] = { 0x1F, 0x8B }; michael@0: SetBuffer(item.StartSignature, sig, 2); michael@0: #endif michael@0: archivers.Add(item); michael@0: } michael@0: #endif michael@0: michael@0: #ifdef FORMAT_SPLIT michael@0: { michael@0: CArchiverInfo item; michael@0: item.UpdateEnabled = false; michael@0: item.KeepName = true; michael@0: item.Name = L"Split"; michael@0: item.Extensions.Add(CArchiverExtInfo(L"001")); michael@0: archivers.Add(item); michael@0: } michael@0: #endif michael@0: michael@0: #ifdef FORMAT_TAR michael@0: { michael@0: CArchiverInfo item; michael@0: item.UpdateEnabled = true; michael@0: item.Name = L"Tar"; michael@0: item.Extensions.Add(CArchiverExtInfo(L"tar")); michael@0: archivers.Add(item); michael@0: } michael@0: #endif michael@0: michael@0: #ifdef FORMAT_ZIP michael@0: { michael@0: CArchiverInfo item; michael@0: item.UpdateEnabled = true; michael@0: item.Name = L"Zip"; michael@0: item.Extensions.Add(CArchiverExtInfo(L"zip")); michael@0: #ifndef _SFX michael@0: const unsigned char sig[] = { 0x50, 0x4B, 0x03, 0x04 }; michael@0: SetBuffer(item.StartSignature, sig, 4); michael@0: #endif michael@0: archivers.Add(item); michael@0: } michael@0: #endif michael@0: michael@0: #ifdef FORMAT_CPIO michael@0: { michael@0: CArchiverInfo item; michael@0: item.Name = L"Cpio"; michael@0: item.Extensions.Add(CArchiverExtInfo(L"cpio")); michael@0: archivers.Add(item); michael@0: } michael@0: #endif michael@0: michael@0: #ifdef FORMAT_RPM michael@0: { michael@0: CArchiverInfo item; michael@0: item.Name = L"Rpm"; michael@0: item.Extensions.Add(CArchiverExtInfo(L"rpm", L".cpio.gz")); michael@0: archivers.Add(item); michael@0: } michael@0: #endif michael@0: michael@0: #ifdef FORMAT_ARJ michael@0: { michael@0: CArchiverInfo item; michael@0: item.Name = L"Arj"; michael@0: item.Extensions.Add(CArchiverExtInfo(L"arj")); michael@0: #ifndef _SFX michael@0: const unsigned char sig[] = { 0x60, 0xEA }; michael@0: SetBuffer(item.StartSignature, sig, 2); michael@0: #endif michael@0: archivers.Add(item); michael@0: } michael@0: #endif michael@0: michael@0: #ifdef FORMAT_Z michael@0: { michael@0: CArchiverInfo item; michael@0: item.Name = L"Z"; michael@0: item.Extensions.Add(CArchiverExtInfo(L"Z")); michael@0: #ifndef _SFX michael@0: const unsigned char sig[] = { 0x1F, 0x9D }; michael@0: SetBuffer(item.StartSignature, sig, 2); michael@0: #endif michael@0: archivers.Add(item); michael@0: } michael@0: #endif michael@0: michael@0: #else michael@0: michael@0: UString folderPath = GetBaseFolderPrefixFromRegistry() + michael@0: (UString)kFormatFolderName + (UString)WSTRING_PATH_SEPARATOR; michael@0: NFind::CEnumeratorW enumerator(folderPath + L"*"); michael@0: NFind::CFileInfoW fileInfo; michael@0: while (enumerator.Next(fileInfo)) michael@0: { michael@0: if (fileInfo.IsDirectory()) michael@0: continue; michael@0: UString filePath = folderPath + fileInfo.Name; michael@0: { michael@0: NDLL::CLibrary library; michael@0: if (!library.LoadEx(filePath, LOAD_LIBRARY_AS_DATAFILE)) michael@0: continue; michael@0: } michael@0: michael@0: NDLL::CLibrary library; michael@0: if (!library.Load(filePath)) michael@0: continue; michael@0: GetHandlerPropertyFunc getHandlerProperty = (GetHandlerPropertyFunc) michael@0: library.GetProcAddress("GetHandlerProperty"); michael@0: if (getHandlerProperty == NULL) michael@0: continue; michael@0: michael@0: CArchiverInfo item; michael@0: item.FilePath = filePath; michael@0: michael@0: NWindows::NCOM::CPropVariant prop; michael@0: if (getHandlerProperty(NArchive::kName, &prop) != S_OK) michael@0: continue; michael@0: if (prop.vt != VT_BSTR) michael@0: continue; michael@0: item.Name = prop.bstrVal; michael@0: prop.Clear(); michael@0: michael@0: if (getHandlerProperty(NArchive::kClassID, &prop) != S_OK) michael@0: continue; michael@0: if (prop.vt != VT_BSTR) michael@0: continue; michael@0: item.ClassID = *(const GUID *)prop.bstrVal; michael@0: prop.Clear(); michael@0: michael@0: if (getHandlerProperty(NArchive::kExtension, &prop) != S_OK) michael@0: continue; michael@0: if (prop.vt != VT_BSTR) michael@0: continue; michael@0: michael@0: UString ext = prop.bstrVal; michael@0: UString addExt; michael@0: michael@0: prop.Clear(); michael@0: michael@0: if (getHandlerProperty(NArchive::kAddExtension, &prop) != S_OK) michael@0: continue; michael@0: if (prop.vt == VT_BSTR) michael@0: { michael@0: addExt = prop.bstrVal; michael@0: } michael@0: else if (prop.vt != VT_EMPTY) michael@0: continue; michael@0: prop.Clear(); michael@0: michael@0: UStringVector exts, addExts; michael@0: SplitString(ext, exts); michael@0: SplitString(addExt, addExts); michael@0: michael@0: prop.Clear(); michael@0: for (int i = 0; i < exts.Size(); i++) michael@0: { michael@0: CArchiverExtInfo extInfo; michael@0: extInfo.Ext = exts[i]; michael@0: if (addExts.Size() > 0) michael@0: extInfo.AddExt = addExts[i]; michael@0: if (extInfo.AddExt == L"*") michael@0: extInfo.AddExt.Empty(); michael@0: item.Extensions.Add(extInfo); michael@0: } michael@0: michael@0: if (getHandlerProperty(NArchive::kUpdate, &prop) == S_OK) michael@0: if (prop.vt == VT_BOOL) michael@0: item.UpdateEnabled = VARIANT_BOOLToBool(prop.boolVal); michael@0: prop.Clear(); michael@0: michael@0: if (item.UpdateEnabled) michael@0: { michael@0: if (getHandlerProperty(NArchive::kKeepName, &prop) == S_OK) michael@0: if (prop.vt == VT_BOOL) michael@0: item.KeepName = VARIANT_BOOLToBool(prop.boolVal); michael@0: prop.Clear(); michael@0: } michael@0: michael@0: if (getHandlerProperty(NArchive::kStartSignature, &prop) == S_OK) michael@0: { michael@0: if (prop.vt == VT_BSTR) michael@0: { michael@0: UINT len = ::SysStringByteLen(prop.bstrVal); michael@0: item.StartSignature.SetCapacity(len); michael@0: memmove(item.StartSignature, prop.bstrVal, len); michael@0: } michael@0: } michael@0: prop.Clear(); michael@0: michael@0: if (getHandlerProperty(NArchive::kAssociate, &prop) == S_OK) michael@0: if (prop.vt == VT_BOOL) michael@0: item.Associate = VARIANT_BOOLToBool(prop.boolVal); michael@0: prop.Clear(); michael@0: michael@0: michael@0: archivers.Add(item); michael@0: } michael@0: michael@0: #endif michael@0: } michael@0: michael@0: