00001
00002
00003
00004
00005 #include "StdAfx.h"
00006
00007 #include "ArchiverInfo.h"
00008
00009 #ifndef EXCLUDE_COM
00010
00011 #include "Common/StringConvert.h"
00012 #include "Windows/FileFind.h"
00013 #include "Windows/FileName.h"
00014 #include "Windows/DLL.h"
00015 #ifdef _WIN32
00016 #include "Windows/Registry.h"
00017 #endif
00018 #include "Windows/PropVariant.h"
00019 #include "../../Archive/IArchive.h"
00020
00021 using namespace NWindows;
00022 using namespace NFile;
00023
00024 #endif
00025
00026 extern HINSTANCE g_hInstance;
00027
00028 #ifndef EXCLUDE_COM
00029
00030 static void SplitString(const UString &srcString, UStringVector &destStrings)
00031 {
00032 destStrings.Clear();
00033 UString string;
00034 int len = srcString.Length();
00035 if (len == 0)
00036 return;
00037 for (int i = 0; i < len; i++)
00038 {
00039 wchar_t c = srcString[i];
00040 if (c == L' ')
00041 {
00042 if (!string.IsEmpty())
00043 {
00044 destStrings.Add(string);
00045 string.Empty();
00046 }
00047 }
00048 else
00049 string += c;
00050 }
00051 if (!string.IsEmpty())
00052 destStrings.Add(string);
00053 }
00054
00055 typedef UInt32 (WINAPI * GetHandlerPropertyFunc)(
00056 PROPID propID, PROPVARIANT *value);
00057
00058 static UString GetModuleFolderPrefix()
00059 {
00060 UString path;
00061 NDLL::MyGetModuleFileName(g_hInstance, path);
00062 int pos = path.ReverseFind(L'\\');
00063 return path.Left(pos + 1);
00064 }
00065
00066 static wchar_t *kFormatFolderName = L"Formats";
00067 static LPCTSTR kRegistryPath = TEXT("Software\\7-zip");
00068 static LPCWSTR kProgramPathValue = L"Path";
00069
00070 #ifdef _WIN32
00071 static bool ReadPathFromRegistry(HKEY baseKey, UString &path)
00072 {
00073 NRegistry::CKey key;
00074 if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
00075 if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS)
00076 {
00077 NName::NormalizeDirPathPrefix(path);
00078 return true;
00079 }
00080 return false;
00081 }
00082 #endif
00083
00084 static UString GetBaseFolderPrefixFromRegistry()
00085 {
00086 UString moduleFolderPrefix = GetModuleFolderPrefix();
00087 NFind::CFileInfoW fileInfo;
00088 if (NFind::FindFile(moduleFolderPrefix + kFormatFolderName, fileInfo))
00089 if (fileInfo.IsDirectory())
00090 return moduleFolderPrefix;
00091 UString path;
00092 #ifdef _WIN32
00093 if(ReadPathFromRegistry(HKEY_CURRENT_USER, path))
00094 return path;
00095 if(ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path))
00096 return path;
00097 #endif
00098 return moduleFolderPrefix;
00099 }
00100
00101 typedef UInt32 (WINAPI *CreateObjectPointer)(
00102 const GUID *clsID,
00103 const GUID *interfaceID,
00104 void **outObject);
00105
00106 #endif
00107
00108 #ifndef _SFX
00109 static void SetBuffer(CByteBuffer &bb, const Byte *data, int size)
00110 {
00111 bb.SetCapacity(size);
00112 memmove((Byte *)bb, data, size);
00113 }
00114 #endif
00115
00116 void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
00117 {
00118 archivers.Clear();
00119
00120 #ifdef EXCLUDE_COM
00121
00122 #ifdef FORMAT_7Z
00123 {
00124 CArchiverInfo item;
00125 item.UpdateEnabled = true;
00126 item.Name = L"7z";
00127 item.Extensions.Add(CArchiverExtInfo(L"7z"));
00128 #ifndef _SFX
00129 const unsigned char kSig[] = {'7' , 'z', 0xBC, 0xAF, 0x27, 0x1C};
00130 SetBuffer(item.StartSignature, kSig, 6);
00131 #endif
00132 archivers.Add(item);
00133 }
00134 #endif
00135
00136 #ifdef FORMAT_BZIP2
00137 {
00138 CArchiverInfo item;
00139 item.UpdateEnabled = true;
00140 item.KeepName = true;
00141 item.Name = L"BZip2";
00142 item.Extensions.Add(CArchiverExtInfo(L"bz2"));
00143 item.Extensions.Add(CArchiverExtInfo(L"tbz2", L".tar"));
00144 #ifndef _SFX
00145 const unsigned char sig[] = {'B' , 'Z', 'h' };
00146 SetBuffer(item.StartSignature, sig, 3);
00147 #endif
00148 archivers.Add(item);
00149 }
00150 #endif
00151
00152 #ifdef FORMAT_GZIP
00153 {
00154 CArchiverInfo item;
00155 item.UpdateEnabled = true;
00156 item.Name = L"GZip";
00157 item.Extensions.Add(CArchiverExtInfo(L"gz"));
00158 item.Extensions.Add(CArchiverExtInfo(L"tgz", L".tar"));
00159 #ifndef _SFX
00160 const unsigned char sig[] = { 0x1F, 0x8B };
00161 SetBuffer(item.StartSignature, sig, 2);
00162 #endif
00163 archivers.Add(item);
00164 }
00165 #endif
00166
00167 #ifdef FORMAT_SPLIT
00168 {
00169 CArchiverInfo item;
00170 item.UpdateEnabled = false;
00171 item.KeepName = true;
00172 item.Name = L"Split";
00173 item.Extensions.Add(CArchiverExtInfo(L"001"));
00174 archivers.Add(item);
00175 }
00176 #endif
00177
00178 #ifdef FORMAT_TAR
00179 {
00180 CArchiverInfo item;
00181 item.UpdateEnabled = true;
00182 item.Name = L"Tar";
00183 item.Extensions.Add(CArchiverExtInfo(L"tar"));
00184 archivers.Add(item);
00185 }
00186 #endif
00187
00188 #ifdef FORMAT_ZIP
00189 {
00190 CArchiverInfo item;
00191 item.UpdateEnabled = true;
00192 item.Name = L"Zip";
00193 item.Extensions.Add(CArchiverExtInfo(L"zip"));
00194 #ifndef _SFX
00195 const unsigned char sig[] = { 0x50, 0x4B, 0x03, 0x04 };
00196 SetBuffer(item.StartSignature, sig, 4);
00197 #endif
00198 archivers.Add(item);
00199 }
00200 #endif
00201
00202 #ifdef FORMAT_CPIO
00203 {
00204 CArchiverInfo item;
00205 item.Name = L"Cpio";
00206 item.Extensions.Add(CArchiverExtInfo(L"cpio"));
00207 archivers.Add(item);
00208 }
00209 #endif
00210
00211 #ifdef FORMAT_RPM
00212 {
00213 CArchiverInfo item;
00214 item.Name = L"Rpm";
00215 item.Extensions.Add(CArchiverExtInfo(L"rpm", L".cpio.gz"));
00216 archivers.Add(item);
00217 }
00218 #endif
00219
00220 #ifdef FORMAT_ARJ
00221 {
00222 CArchiverInfo item;
00223 item.Name = L"Arj";
00224 item.Extensions.Add(CArchiverExtInfo(L"arj"));
00225 #ifndef _SFX
00226 const unsigned char sig[] = { 0x60, 0xEA };
00227 SetBuffer(item.StartSignature, sig, 2);
00228 #endif
00229 archivers.Add(item);
00230 }
00231 #endif
00232
00233 #ifdef FORMAT_Z
00234 {
00235 CArchiverInfo item;
00236 item.Name = L"Z";
00237 item.Extensions.Add(CArchiverExtInfo(L"Z"));
00238 #ifndef _SFX
00239 const unsigned char sig[] = { 0x1F, 0x9D };
00240 SetBuffer(item.StartSignature, sig, 2);
00241 #endif
00242 archivers.Add(item);
00243 }
00244 #endif
00245
00246 #else
00247
00248 UString folderPath = GetBaseFolderPrefixFromRegistry() +
00249 kFormatFolderName + L"\\";
00250 NFind::CEnumeratorW enumerator(folderPath + L"*");
00251 NFind::CFileInfoW fileInfo;
00252 while (enumerator.Next(fileInfo))
00253 {
00254 if (fileInfo.IsDirectory())
00255 continue;
00256 UString filePath = folderPath + fileInfo.Name;
00257 {
00258 NDLL::CLibrary library;
00259 if (!library.LoadEx(filePath, LOAD_LIBRARY_AS_DATAFILE))
00260 continue;
00261 }
00262
00263 NDLL::CLibrary library;
00264 if (!library.Load(filePath))
00265 continue;
00266 GetHandlerPropertyFunc getHandlerProperty = (GetHandlerPropertyFunc)
00267 library.GetProcAddress("GetHandlerProperty");
00268 if (getHandlerProperty == NULL)
00269 continue;
00270
00271 CArchiverInfo item;
00272 item.FilePath = filePath;
00273
00274 NWindows::NCOM::CPropVariant prop;
00275 if (getHandlerProperty(NArchive::kName, &prop) != S_OK)
00276 continue;
00277 if (prop.vt != VT_BSTR)
00278 continue;
00279 item.Name = prop.bstrVal;
00280 prop.Clear();
00281
00282 if (getHandlerProperty(NArchive::kClassID, &prop) != S_OK)
00283 continue;
00284 if (prop.vt != VT_BSTR)
00285 continue;
00286 item.ClassID = *(const GUID *)prop.bstrVal;
00287 prop.Clear();
00288
00289 if (getHandlerProperty(NArchive::kExtension, &prop) != S_OK)
00290 continue;
00291 if (prop.vt != VT_BSTR)
00292 continue;
00293
00294 UString ext = prop.bstrVal;
00295 UString addExt;
00296
00297 prop.Clear();
00298
00299 if (getHandlerProperty(NArchive::kAddExtension, &prop) != S_OK)
00300 continue;
00301 if (prop.vt == VT_BSTR)
00302 {
00303 addExt = prop.bstrVal;
00304 }
00305 else if (prop.vt != VT_EMPTY)
00306 continue;
00307 prop.Clear();
00308
00309 UStringVector exts, addExts;
00310 SplitString(ext, exts);
00311 SplitString(addExt, addExts);
00312
00313 prop.Clear();
00314 for (int i = 0; i < exts.Size(); i++)
00315 {
00316 CArchiverExtInfo extInfo;
00317 extInfo.Ext = exts[i];
00318 if (addExts.Size() > 0)
00319 extInfo.AddExt = addExts[i];
00320 if (extInfo.AddExt == L"*")
00321 extInfo.AddExt.Empty();
00322 item.Extensions.Add(extInfo);
00323 }
00324
00325 if (getHandlerProperty(NArchive::kUpdate, &prop) == S_OK)
00326 if (prop.vt == VT_BOOL)
00327 item.UpdateEnabled = VARIANT_BOOLToBool(prop.boolVal);
00328 prop.Clear();
00329
00330 if (item.UpdateEnabled)
00331 {
00332 if (getHandlerProperty(NArchive::kKeepName, &prop) == S_OK)
00333 if (prop.vt == VT_BOOL)
00334 item.KeepName = VARIANT_BOOLToBool(prop.boolVal);
00335 prop.Clear();
00336 }
00337
00338 if (getHandlerProperty(NArchive::kStartSignature, &prop) == S_OK)
00339 {
00340 if (prop.vt == VT_BSTR)
00341 {
00342 UINT len = ::SysStringByteLen(prop.bstrVal);
00343 item.StartSignature.SetCapacity(len);
00344 memmove(item.StartSignature, prop.bstrVal, len);
00345 }
00346 }
00347 prop.Clear();
00348
00349 if (getHandlerProperty(NArchive::kAssociate, &prop) == S_OK)
00350 if (prop.vt == VT_BOOL)
00351 item.Associate = VARIANT_BOOLToBool(prop.boolVal);
00352 prop.Clear();
00353
00354 archivers.Add(item);
00355 }
00356
00357 #endif
00358 }
00359