// ZipRegistry.cpp #include "StdAfx.h" #include "../../../../C/CpuArch.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringToInt.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/Registry.h" #include "../../../Windows/Synchronization.h" // #include "../Explorer/ContextMenuFlags.h" #include "ZipRegistry.h" using namespace NWindows; using namespace NRegistry; static NSynchronization::CCriticalSection g_CS; #define CS_LOCK NSynchronization::CCriticalSectionLock lock(g_CS); static LPCTSTR const kCuPrefix = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR); static CSysString GetKeyPath(LPCTSTR path) { return kCuPrefix + (CSysString)path; } static LONG OpenMainKey(CKey &key, LPCTSTR keyName) { return key.Open(HKEY_CURRENT_USER, GetKeyPath(keyName), KEY_READ); } static LONG CreateMainKey(CKey &key, LPCTSTR keyName) { return key.Create(HKEY_CURRENT_USER, GetKeyPath(keyName)); } static void Key_Set_UInt32(CKey &key, LPCTSTR name, UInt32 value) { if (value == (UInt32)(Int32)-1) key.DeleteValue(name); else key.SetValue(name, value); } static void Key_Get_UInt32(CKey &key, LPCTSTR name, UInt32 &value) { value = (UInt32)(Int32)-1; key.GetValue_UInt32_IfOk(name, value); } static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b) { if (b.Def) key.SetValue(name, b.Val); } static void Key_Set_bool_if_Changed(CKey &key, LPCTSTR name, bool val) { bool oldVal = false; if (key.GetValue_bool_IfOk(name, oldVal) == ERROR_SUCCESS) if (val == oldVal) return; key.SetValue(name, val); } static void Key_Set_BoolPair_Delete_IfNotDef(CKey &key, LPCTSTR name, const CBoolPair &b) { if (b.Def) Key_Set_bool_if_Changed(key, name, b.Val); else key.DeleteValue(name); } static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b) { b.Val = false; b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS); } static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b) { b.Val = true; b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS); } namespace NExtract { static LPCTSTR const kKeyName = TEXT("Extraction"); static LPCTSTR const kExtractMode = TEXT("ExtractMode"); static LPCTSTR const kOverwriteMode = TEXT("OverwriteMode"); static LPCTSTR const kShowPassword = TEXT("ShowPassword"); static LPCTSTR const kPathHistory = TEXT("PathHistory"); static LPCTSTR const kSplitDest = TEXT("SplitDest"); static LPCTSTR const kElimDup = TEXT("ElimDup"); // static LPCTSTR const kAltStreams = TEXT("AltStreams"); static LPCTSTR const kNtSecur = TEXT("Security"); static LPCTSTR const kMemLimit = TEXT("MemLimit"); void CInfo::Save() const { CS_LOCK CKey key; CreateMainKey(key, kKeyName); if (PathMode_Force) key.SetValue(kExtractMode, (UInt32)PathMode); if (OverwriteMode_Force) key.SetValue(kOverwriteMode, (UInt32)OverwriteMode); Key_Set_BoolPair(key, kSplitDest, SplitDest); Key_Set_BoolPair(key, kElimDup, ElimDup); // Key_Set_BoolPair(key, kAltStreams, AltStreams); Key_Set_BoolPair(key, kNtSecur, NtSecurity); Key_Set_BoolPair(key, kShowPassword, ShowPassword); key.RecurseDeleteKey(kPathHistory); key.SetValue_Strings(kPathHistory, Paths); } void Save_ShowPassword(bool showPassword) { CS_LOCK CKey key; CreateMainKey(key, kKeyName); key.SetValue(kShowPassword, showPassword); } void Save_LimitGB(UInt32 limit_GB) { CS_LOCK CKey key; CreateMainKey(key, kKeyName); Key_Set_UInt32(key, kMemLimit, limit_GB); } void CInfo::Load() { PathMode = NPathMode::kCurPaths; PathMode_Force = false; OverwriteMode = NOverwriteMode::kAsk; OverwriteMode_Force = false; SplitDest.Val = true; Paths.Clear(); CS_LOCK CKey key; if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) return; key.GetValue_Strings(kPathHistory, Paths); UInt32 v; if (key.GetValue_UInt32_IfOk(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths) { PathMode = (NPathMode::EEnum)v; PathMode_Force = true; } if (key.GetValue_UInt32_IfOk(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting) { OverwriteMode = (NOverwriteMode::EEnum)v; OverwriteMode_Force = true; } Key_Get_BoolPair_true(key, kSplitDest, SplitDest); Key_Get_BoolPair(key, kElimDup, ElimDup); // Key_Get_BoolPair(key, kAltStreams, AltStreams); Key_Get_BoolPair(key, kNtSecur, NtSecurity); Key_Get_BoolPair(key, kShowPassword, ShowPassword); } bool Read_ShowPassword() { CS_LOCK CKey key; bool showPassword = false; if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) return showPassword; key.GetValue_bool_IfOk(kShowPassword, showPassword); return showPassword; } UInt32 Read_LimitGB() { CS_LOCK CKey key; UInt32 v = (UInt32)(Int32)-1; if (OpenMainKey(key, kKeyName) == ERROR_SUCCESS) key.GetValue_UInt32_IfOk(kMemLimit, v); return v; } } namespace NCompression { static LPCTSTR const kKeyName = TEXT("Compression"); static LPCTSTR const kArcHistory = TEXT("ArcHistory"); static LPCWSTR const kArchiver = L"Archiver"; static LPCTSTR const kShowPassword = TEXT("ShowPassword"); static LPCTSTR const kEncryptHeaders = TEXT("EncryptHeaders"); static LPCTSTR const kOptionsKeyName = TEXT("Options"); static LPCTSTR const kLevel = TEXT("Level"); static LPCTSTR const kDictionary = TEXT("Dictionary"); // static LPCTSTR const kDictionaryChain = TEXT("DictionaryChain"); static LPCTSTR const kOrder = TEXT("Order"); static LPCTSTR const kBlockSize = TEXT("BlockSize"); static LPCTSTR const kNumThreads = TEXT("NumThreads"); static LPCWSTR const kMethod = L"Method"; static LPCWSTR const kOptions = L"Options"; static LPCWSTR const kEncryptionMethod = L"EncryptionMethod"; static LPCTSTR const kNtSecur = TEXT("Security"); static LPCTSTR const kAltStreams = TEXT("AltStreams"); static LPCTSTR const kHardLinks = TEXT("HardLinks"); static LPCTSTR const kSymLinks = TEXT("SymLinks"); static LPCTSTR const kPreserveATime = TEXT("PreserveATime"); static LPCTSTR const kTimePrec = TEXT("TimePrec"); static LPCTSTR const kMTime = TEXT("MTime"); static LPCTSTR const kATime = TEXT("ATime"); static LPCTSTR const kCTime = TEXT("CTime"); static LPCTSTR const kSetArcMTime = TEXT("SetArcMTime"); static void SetRegString(CKey &key, LPCWSTR name, const UString &value) { if (value.IsEmpty()) key.DeleteValue(name); else key.SetValue(name, value); } static void GetRegString(CKey &key, LPCWSTR name, UString &value) { if (key.QueryValue(name, value) != ERROR_SUCCESS) value.Empty(); } static LPCWSTR const kMemUse = L"MemUse" #if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) L"32"; #else L"64"; #endif void CInfo::Save() const { CS_LOCK CKey key; CreateMainKey(key, kKeyName); Key_Set_BoolPair_Delete_IfNotDef (key, kNtSecur, NtSecurity); Key_Set_BoolPair_Delete_IfNotDef (key, kAltStreams, AltStreams); Key_Set_BoolPair_Delete_IfNotDef (key, kHardLinks, HardLinks); Key_Set_BoolPair_Delete_IfNotDef (key, kSymLinks, SymLinks); Key_Set_BoolPair_Delete_IfNotDef (key, kPreserveATime, PreserveATime); key.SetValue(kShowPassword, ShowPassword); key.SetValue(kLevel, (UInt32)Level); key.SetValue(kArchiver, ArcType); key.SetValue(kShowPassword, ShowPassword); key.SetValue(kEncryptHeaders, EncryptHeaders); key.RecurseDeleteKey(kArcHistory); key.SetValue_Strings(kArcHistory, ArcPaths); key.RecurseDeleteKey(kOptionsKeyName); { CKey optionsKey; optionsKey.Create(key, kOptionsKeyName); FOR_VECTOR (i, Formats) { const CFormatOptions &fo = Formats[i]; CKey fk; fk.Create(optionsKey, fo.FormatID); SetRegString(fk, kMethod, fo.Method); SetRegString(fk, kOptions, fo.Options); SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod); SetRegString(fk, kMemUse, fo.MemUse); Key_Set_UInt32(fk, kLevel, fo.Level); Key_Set_UInt32(fk, kDictionary, fo.Dictionary); // Key_Set_UInt32(fk, kDictionaryChain, fo.DictionaryChain); Key_Set_UInt32(fk, kOrder, fo.Order); Key_Set_UInt32(fk, kBlockSize, fo.BlockLogSize); Key_Set_UInt32(fk, kNumThreads, fo.NumThreads); Key_Set_UInt32(fk, kTimePrec, fo.TimePrec); Key_Set_BoolPair_Delete_IfNotDef (fk, kMTime, fo.MTime); Key_Set_BoolPair_Delete_IfNotDef (fk, kATime, fo.ATime); Key_Set_BoolPair_Delete_IfNotDef (fk, kCTime, fo.CTime); Key_Set_BoolPair_Delete_IfNotDef (fk, kSetArcMTime, fo.SetArcMTime); } } } void CInfo::Load() { ArcPaths.Clear(); Formats.Clear(); Level = 5; ArcType = L"7z"; ShowPassword = false; EncryptHeaders = false; CS_LOCK CKey key; if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) return; Key_Get_BoolPair(key, kNtSecur, NtSecurity); Key_Get_BoolPair(key, kAltStreams, AltStreams); Key_Get_BoolPair(key, kHardLinks, HardLinks); Key_Get_BoolPair(key, kSymLinks, SymLinks); Key_Get_BoolPair(key, kPreserveATime, PreserveATime); key.GetValue_Strings(kArcHistory, ArcPaths); { CKey optionsKey; if (optionsKey.Open(key, kOptionsKeyName, KEY_READ) == ERROR_SUCCESS) { CSysStringVector formatIDs; optionsKey.EnumKeys(formatIDs); FOR_VECTOR (i, formatIDs) { CKey fk; CFormatOptions fo; fo.FormatID = formatIDs[i]; if (fk.Open(optionsKey, fo.FormatID, KEY_READ) == ERROR_SUCCESS) { GetRegString(fk, kMethod, fo.Method); GetRegString(fk, kOptions, fo.Options); GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod); GetRegString(fk, kMemUse, fo.MemUse); Key_Get_UInt32(fk, kLevel, fo.Level); Key_Get_UInt32(fk, kDictionary, fo.Dictionary); // Key_Get_UInt32(fk, kDictionaryChain, fo.DictionaryChain); Key_Get_UInt32(fk, kOrder, fo.Order); Key_Get_UInt32(fk, kBlockSize, fo.BlockLogSize); Key_Get_UInt32(fk, kNumThreads, fo.NumThreads); Key_Get_UInt32(fk, kTimePrec, fo.TimePrec); Key_Get_BoolPair(fk, kMTime, fo.MTime); Key_Get_BoolPair(fk, kATime, fo.ATime); Key_Get_BoolPair(fk, kCTime, fo.CTime); Key_Get_BoolPair(fk, kSetArcMTime, fo.SetArcMTime); Formats.Add(fo); } } } } UString a; if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS) ArcType = a; key.GetValue_UInt32_IfOk(kLevel, Level); key.GetValue_bool_IfOk(kShowPassword, ShowPassword); key.GetValue_bool_IfOk(kEncryptHeaders, EncryptHeaders); } static bool ParseMemUse(const wchar_t *s, CMemUse &mu) { mu.Clear(); bool percentMode = false; { const wchar_t c = *s; if (MyCharLower_Ascii(c) == 'p') { percentMode = true; s++; } } const wchar_t *end; UInt64 number = ConvertStringToUInt64(s, &end); if (end == s) return false; wchar_t c = *end; if (percentMode) { if (c != 0) return false; mu.IsPercent = true; mu.Val = number; return true; } if (c == 0) { mu.Val = number; return true; } c = MyCharLower_Ascii(c); const wchar_t c1 = end[1]; if (c == '%') { if (c1 != 0) return false; mu.IsPercent = true; mu.Val = number; return true; } if (c == 'b') { if (c1 != 0) return false; mu.Val = number; return true; } if (c1 != 0) if (MyCharLower_Ascii(c1) != 'b' || end[2] != 0) return false; unsigned numBits; switch (c) { case 'k': numBits = 10; break; case 'm': numBits = 20; break; case 'g': numBits = 30; break; case 't': numBits = 40; break; default: return false; } if (number >= ((UInt64)1 << (64 - numBits))) return false; mu.Val = number << numBits; return true; } void CMemUse::Parse(const UString &s) { IsDefined = ParseMemUse(s, *this); } /* void MemLimit_Save(const UString &s) { CS_LOCK CKey key; CreateMainKey(key, kKeyName); SetRegString(key, kMemUse, s); } bool MemLimit_Load(NCompression::CMemUse &mu) { mu.Clear(); UString a; { CS_LOCK CKey key; if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) return false; if (key.QueryValue(kMemUse, a) != ERROR_SUCCESS) return false; } if (a.IsEmpty()) return false; mu.Parse(a); return mu.IsDefined; } */ } static LPCTSTR const kOptionsInfoKeyName = TEXT("Options"); namespace NWorkDir { static LPCTSTR const kWorkDirType = TEXT("WorkDirType"); static LPCWSTR const kWorkDirPath = L"WorkDirPath"; static LPCTSTR const kTempRemovableOnly = TEXT("TempRemovableOnly"); void CInfo::Save()const { CS_LOCK CKey key; CreateMainKey(key, kOptionsInfoKeyName); key.SetValue(kWorkDirType, (UInt32)Mode); key.SetValue(kWorkDirPath, fs2us(Path)); key.SetValue(kTempRemovableOnly, ForRemovableOnly); } void CInfo::Load() { SetDefault(); CS_LOCK CKey key; if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS) return; UInt32 dirType; if (key.GetValue_UInt32_IfOk(kWorkDirType, dirType) != ERROR_SUCCESS) return; switch (dirType) { case NMode::kSystem: case NMode::kCurrent: case NMode::kSpecified: Mode = (NMode::EEnum)dirType; } UString pathU; if (key.QueryValue(kWorkDirPath, pathU) == ERROR_SUCCESS) Path = us2fs(pathU); else { Path.Empty(); if (Mode == NMode::kSpecified) Mode = NMode::kSystem; } key.GetValue_bool_IfOk(kTempRemovableOnly, ForRemovableOnly); } } static LPCTSTR const kCascadedMenu = TEXT("CascadedMenu"); static LPCTSTR const kContextMenu = TEXT("ContextMenu"); static LPCTSTR const kMenuIcons = TEXT("MenuIcons"); static LPCTSTR const kElimDup = TEXT("ElimDupExtract"); static LPCTSTR const kWriteZoneId = TEXT("WriteZoneIdExtract"); void CContextMenuInfo::Save() const { CS_LOCK CKey key; CreateMainKey(key, kOptionsInfoKeyName); Key_Set_BoolPair(key, kCascadedMenu, Cascaded); Key_Set_BoolPair(key, kMenuIcons, MenuIcons); Key_Set_BoolPair(key, kElimDup, ElimDup); Key_Set_UInt32(key, kWriteZoneId, WriteZone); if (Flags_Def) key.SetValue(kContextMenu, Flags); } void CContextMenuInfo::Load() { Cascaded.Val = true; Cascaded.Def = false; MenuIcons.Val = false; MenuIcons.Def = false; ElimDup.Val = true; ElimDup.Def = false; WriteZone = (UInt32)(Int32)-1; /* we can disable email items by default, because email code doesn't work in some systems */ Flags = (UInt32)(Int32)-1 /* & ~NContextMenuFlags::kCompressEmail & ~NContextMenuFlags::kCompressTo7zEmail & ~NContextMenuFlags::kCompressToZipEmail */ ; Flags_Def = false; CS_LOCK CKey key; if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS) return; Key_Get_BoolPair_true(key, kCascadedMenu, Cascaded); Key_Get_BoolPair_true(key, kElimDup, ElimDup); Key_Get_BoolPair(key, kMenuIcons, MenuIcons); Key_Get_UInt32(key, kWriteZoneId, WriteZone); Flags_Def = (key.GetValue_UInt32_IfOk(kContextMenu, Flags) == ERROR_SUCCESS); }