1 // ZipRegistry.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../../C/CpuArch.h"
6
7 #include "../../../Common/IntToString.h"
8 #include "../../../Common/StringToInt.h"
9
10 #include "../../../Windows/FileDir.h"
11 #include "../../../Windows/Registry.h"
12 #include "../../../Windows/Synchronization.h"
13
14 // #include "../Explorer/ContextMenuFlags.h"
15 #include "ZipRegistry.h"
16
17 using namespace NWindows;
18 using namespace NRegistry;
19
20 static NSynchronization::CCriticalSection g_CS;
21 #define CS_LOCK NSynchronization::CCriticalSectionLock lock(g_CS);
22
23 static LPCTSTR const kCuPrefix = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR);
24
GetKeyPath(LPCTSTR path)25 static CSysString GetKeyPath(LPCTSTR path) { return kCuPrefix + (CSysString)path; }
26
OpenMainKey(CKey & key,LPCTSTR keyName)27 static LONG OpenMainKey(CKey &key, LPCTSTR keyName)
28 {
29 return key.Open(HKEY_CURRENT_USER, GetKeyPath(keyName), KEY_READ);
30 }
31
CreateMainKey(CKey & key,LPCTSTR keyName)32 static LONG CreateMainKey(CKey &key, LPCTSTR keyName)
33 {
34 return key.Create(HKEY_CURRENT_USER, GetKeyPath(keyName));
35 }
36
Key_Set_UInt32(CKey & key,LPCTSTR name,UInt32 value)37 static void Key_Set_UInt32(CKey &key, LPCTSTR name, UInt32 value)
38 {
39 if (value == (UInt32)(Int32)-1)
40 key.DeleteValue(name);
41 else
42 key.SetValue(name, value);
43 }
44
45
Key_Get_UInt32(CKey & key,LPCTSTR name,UInt32 & value)46 static void Key_Get_UInt32(CKey &key, LPCTSTR name, UInt32 &value)
47 {
48 value = (UInt32)(Int32)-1;
49 key.GetValue_UInt32_IfOk(name, value);
50 }
51
52
Key_Set_BoolPair(CKey & key,LPCTSTR name,const CBoolPair & b)53 static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b)
54 {
55 if (b.Def)
56 key.SetValue(name, b.Val);
57 }
58
Key_Set_bool_if_Changed(CKey & key,LPCTSTR name,bool val)59 static void Key_Set_bool_if_Changed(CKey &key, LPCTSTR name, bool val)
60 {
61 bool oldVal = false;
62 if (key.GetValue_bool_IfOk(name, oldVal) == ERROR_SUCCESS)
63 if (val == oldVal)
64 return;
65 key.SetValue(name, val);
66 }
67
Key_Set_BoolPair_Delete_IfNotDef(CKey & key,LPCTSTR name,const CBoolPair & b)68 static void Key_Set_BoolPair_Delete_IfNotDef(CKey &key, LPCTSTR name, const CBoolPair &b)
69 {
70 if (b.Def)
71 Key_Set_bool_if_Changed(key, name, b.Val);
72 else
73 key.DeleteValue(name);
74 }
75
Key_Get_BoolPair(CKey & key,LPCTSTR name,CBoolPair & b)76 static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b)
77 {
78 b.Val = false;
79 b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS);
80 }
81
Key_Get_BoolPair_true(CKey & key,LPCTSTR name,CBoolPair & b)82 static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b)
83 {
84 b.Val = true;
85 b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS);
86 }
87
88 namespace NExtract
89 {
90
91 static LPCTSTR const kKeyName = TEXT("Extraction");
92
93 static LPCTSTR const kExtractMode = TEXT("ExtractMode");
94 static LPCTSTR const kOverwriteMode = TEXT("OverwriteMode");
95 static LPCTSTR const kShowPassword = TEXT("ShowPassword");
96 static LPCTSTR const kPathHistory = TEXT("PathHistory");
97 static LPCTSTR const kSplitDest = TEXT("SplitDest");
98 static LPCTSTR const kElimDup = TEXT("ElimDup");
99 // static LPCTSTR const kAltStreams = TEXT("AltStreams");
100 static LPCTSTR const kNtSecur = TEXT("Security");
101 static LPCTSTR const kMemLimit = TEXT("MemLimit");
102
Save() const103 void CInfo::Save() const
104 {
105 CS_LOCK
106 CKey key;
107 CreateMainKey(key, kKeyName);
108
109 if (PathMode_Force)
110 key.SetValue(kExtractMode, (UInt32)PathMode);
111 if (OverwriteMode_Force)
112 key.SetValue(kOverwriteMode, (UInt32)OverwriteMode);
113
114 Key_Set_BoolPair(key, kSplitDest, SplitDest);
115 Key_Set_BoolPair(key, kElimDup, ElimDup);
116 // Key_Set_BoolPair(key, kAltStreams, AltStreams);
117 Key_Set_BoolPair(key, kNtSecur, NtSecurity);
118 Key_Set_BoolPair(key, kShowPassword, ShowPassword);
119
120 key.RecurseDeleteKey(kPathHistory);
121 key.SetValue_Strings(kPathHistory, Paths);
122 }
123
Save_ShowPassword(bool showPassword)124 void Save_ShowPassword(bool showPassword)
125 {
126 CS_LOCK
127 CKey key;
128 CreateMainKey(key, kKeyName);
129 key.SetValue(kShowPassword, showPassword);
130 }
131
Save_LimitGB(UInt32 limit_GB)132 void Save_LimitGB(UInt32 limit_GB)
133 {
134 CS_LOCK
135 CKey key;
136 CreateMainKey(key, kKeyName);
137 Key_Set_UInt32(key, kMemLimit, limit_GB);
138 }
139
Load()140 void CInfo::Load()
141 {
142 PathMode = NPathMode::kCurPaths;
143 PathMode_Force = false;
144 OverwriteMode = NOverwriteMode::kAsk;
145 OverwriteMode_Force = false;
146
147 SplitDest.Val = true;
148
149 Paths.Clear();
150
151 CS_LOCK
152 CKey key;
153 if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
154 return;
155
156 key.GetValue_Strings(kPathHistory, Paths);
157 UInt32 v;
158 if (key.GetValue_UInt32_IfOk(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths)
159 {
160 PathMode = (NPathMode::EEnum)v;
161 PathMode_Force = true;
162 }
163 if (key.GetValue_UInt32_IfOk(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting)
164 {
165 OverwriteMode = (NOverwriteMode::EEnum)v;
166 OverwriteMode_Force = true;
167 }
168
169 Key_Get_BoolPair_true(key, kSplitDest, SplitDest);
170
171 Key_Get_BoolPair(key, kElimDup, ElimDup);
172 // Key_Get_BoolPair(key, kAltStreams, AltStreams);
173 Key_Get_BoolPair(key, kNtSecur, NtSecurity);
174 Key_Get_BoolPair(key, kShowPassword, ShowPassword);
175 }
176
Read_ShowPassword()177 bool Read_ShowPassword()
178 {
179 CS_LOCK
180 CKey key;
181 bool showPassword = false;
182 if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
183 return showPassword;
184 key.GetValue_bool_IfOk(kShowPassword, showPassword);
185 return showPassword;
186 }
187
Read_LimitGB()188 UInt32 Read_LimitGB()
189 {
190 CS_LOCK
191 CKey key;
192 UInt32 v = (UInt32)(Int32)-1;
193 if (OpenMainKey(key, kKeyName) == ERROR_SUCCESS)
194 key.GetValue_UInt32_IfOk(kMemLimit, v);
195 return v;
196 }
197
198 }
199
200 namespace NCompression
201 {
202
203 static LPCTSTR const kKeyName = TEXT("Compression");
204
205 static LPCTSTR const kArcHistory = TEXT("ArcHistory");
206 static LPCWSTR const kArchiver = L"Archiver";
207 static LPCTSTR const kShowPassword = TEXT("ShowPassword");
208 static LPCTSTR const kEncryptHeaders = TEXT("EncryptHeaders");
209
210 static LPCTSTR const kOptionsKeyName = TEXT("Options");
211
212 static LPCTSTR const kLevel = TEXT("Level");
213 static LPCTSTR const kDictionary = TEXT("Dictionary");
214 // static LPCTSTR const kDictionaryChain = TEXT("DictionaryChain");
215 static LPCTSTR const kOrder = TEXT("Order");
216 static LPCTSTR const kBlockSize = TEXT("BlockSize");
217 static LPCTSTR const kNumThreads = TEXT("NumThreads");
218 static LPCWSTR const kMethod = L"Method";
219 static LPCWSTR const kOptions = L"Options";
220 static LPCWSTR const kEncryptionMethod = L"EncryptionMethod";
221
222 static LPCTSTR const kNtSecur = TEXT("Security");
223 static LPCTSTR const kAltStreams = TEXT("AltStreams");
224 static LPCTSTR const kHardLinks = TEXT("HardLinks");
225 static LPCTSTR const kSymLinks = TEXT("SymLinks");
226 static LPCTSTR const kPreserveATime = TEXT("PreserveATime");
227
228 static LPCTSTR const kTimePrec = TEXT("TimePrec");
229 static LPCTSTR const kMTime = TEXT("MTime");
230 static LPCTSTR const kATime = TEXT("ATime");
231 static LPCTSTR const kCTime = TEXT("CTime");
232 static LPCTSTR const kSetArcMTime = TEXT("SetArcMTime");
233
SetRegString(CKey & key,LPCWSTR name,const UString & value)234 static void SetRegString(CKey &key, LPCWSTR name, const UString &value)
235 {
236 if (value.IsEmpty())
237 key.DeleteValue(name);
238 else
239 key.SetValue(name, value);
240 }
241
GetRegString(CKey & key,LPCWSTR name,UString & value)242 static void GetRegString(CKey &key, LPCWSTR name, UString &value)
243 {
244 if (key.QueryValue(name, value) != ERROR_SUCCESS)
245 value.Empty();
246 }
247
248 static LPCWSTR const kMemUse = L"MemUse"
249 #if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
250 L"32";
251 #else
252 L"64";
253 #endif
254
Save() const255 void CInfo::Save() const
256 {
257 CS_LOCK
258
259 CKey key;
260 CreateMainKey(key, kKeyName);
261
262 Key_Set_BoolPair_Delete_IfNotDef (key, kNtSecur, NtSecurity);
263 Key_Set_BoolPair_Delete_IfNotDef (key, kAltStreams, AltStreams);
264 Key_Set_BoolPair_Delete_IfNotDef (key, kHardLinks, HardLinks);
265 Key_Set_BoolPair_Delete_IfNotDef (key, kSymLinks, SymLinks);
266 Key_Set_BoolPair_Delete_IfNotDef (key, kPreserveATime, PreserveATime);
267
268 key.SetValue(kShowPassword, ShowPassword);
269 key.SetValue(kLevel, (UInt32)Level);
270 key.SetValue(kArchiver, ArcType);
271 key.SetValue(kShowPassword, ShowPassword);
272 key.SetValue(kEncryptHeaders, EncryptHeaders);
273 key.RecurseDeleteKey(kArcHistory);
274 key.SetValue_Strings(kArcHistory, ArcPaths);
275
276 key.RecurseDeleteKey(kOptionsKeyName);
277 {
278 CKey optionsKey;
279 optionsKey.Create(key, kOptionsKeyName);
280 FOR_VECTOR (i, Formats)
281 {
282 const CFormatOptions &fo = Formats[i];
283 CKey fk;
284 fk.Create(optionsKey, fo.FormatID);
285
286 SetRegString(fk, kMethod, fo.Method);
287 SetRegString(fk, kOptions, fo.Options);
288 SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
289 SetRegString(fk, kMemUse, fo.MemUse);
290
291 Key_Set_UInt32(fk, kLevel, fo.Level);
292 Key_Set_UInt32(fk, kDictionary, fo.Dictionary);
293 // Key_Set_UInt32(fk, kDictionaryChain, fo.DictionaryChain);
294 Key_Set_UInt32(fk, kOrder, fo.Order);
295 Key_Set_UInt32(fk, kBlockSize, fo.BlockLogSize);
296 Key_Set_UInt32(fk, kNumThreads, fo.NumThreads);
297
298 Key_Set_UInt32(fk, kTimePrec, fo.TimePrec);
299 Key_Set_BoolPair_Delete_IfNotDef (fk, kMTime, fo.MTime);
300 Key_Set_BoolPair_Delete_IfNotDef (fk, kATime, fo.ATime);
301 Key_Set_BoolPair_Delete_IfNotDef (fk, kCTime, fo.CTime);
302 Key_Set_BoolPair_Delete_IfNotDef (fk, kSetArcMTime, fo.SetArcMTime);
303 }
304 }
305 }
306
Load()307 void CInfo::Load()
308 {
309 ArcPaths.Clear();
310 Formats.Clear();
311
312 Level = 5;
313 ArcType = L"7z";
314 ShowPassword = false;
315 EncryptHeaders = false;
316
317 CS_LOCK
318 CKey key;
319
320 if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
321 return;
322
323 Key_Get_BoolPair(key, kNtSecur, NtSecurity);
324 Key_Get_BoolPair(key, kAltStreams, AltStreams);
325 Key_Get_BoolPair(key, kHardLinks, HardLinks);
326 Key_Get_BoolPair(key, kSymLinks, SymLinks);
327 Key_Get_BoolPair(key, kPreserveATime, PreserveATime);
328
329 key.GetValue_Strings(kArcHistory, ArcPaths);
330
331 {
332 CKey optionsKey;
333 if (optionsKey.Open(key, kOptionsKeyName, KEY_READ) == ERROR_SUCCESS)
334 {
335 CSysStringVector formatIDs;
336 optionsKey.EnumKeys(formatIDs);
337 FOR_VECTOR (i, formatIDs)
338 {
339 CKey fk;
340 CFormatOptions fo;
341 fo.FormatID = formatIDs[i];
342 if (fk.Open(optionsKey, fo.FormatID, KEY_READ) == ERROR_SUCCESS)
343 {
344 GetRegString(fk, kMethod, fo.Method);
345 GetRegString(fk, kOptions, fo.Options);
346 GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
347 GetRegString(fk, kMemUse, fo.MemUse);
348
349 Key_Get_UInt32(fk, kLevel, fo.Level);
350 Key_Get_UInt32(fk, kDictionary, fo.Dictionary);
351 // Key_Get_UInt32(fk, kDictionaryChain, fo.DictionaryChain);
352 Key_Get_UInt32(fk, kOrder, fo.Order);
353 Key_Get_UInt32(fk, kBlockSize, fo.BlockLogSize);
354 Key_Get_UInt32(fk, kNumThreads, fo.NumThreads);
355
356 Key_Get_UInt32(fk, kTimePrec, fo.TimePrec);
357 Key_Get_BoolPair(fk, kMTime, fo.MTime);
358 Key_Get_BoolPair(fk, kATime, fo.ATime);
359 Key_Get_BoolPair(fk, kCTime, fo.CTime);
360 Key_Get_BoolPair(fk, kSetArcMTime, fo.SetArcMTime);
361
362 Formats.Add(fo);
363 }
364 }
365 }
366 }
367
368 UString a;
369 if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS)
370 ArcType = a;
371 key.GetValue_UInt32_IfOk(kLevel, Level);
372 key.GetValue_bool_IfOk(kShowPassword, ShowPassword);
373 key.GetValue_bool_IfOk(kEncryptHeaders, EncryptHeaders);
374 }
375
376
ParseMemUse(const wchar_t * s,CMemUse & mu)377 static bool ParseMemUse(const wchar_t *s, CMemUse &mu)
378 {
379 mu.Clear();
380
381 bool percentMode = false;
382 {
383 const wchar_t c = *s;
384 if (MyCharLower_Ascii(c) == 'p')
385 {
386 percentMode = true;
387 s++;
388 }
389 }
390 const wchar_t *end;
391 UInt64 number = ConvertStringToUInt64(s, &end);
392 if (end == s)
393 return false;
394
395 wchar_t c = *end;
396
397 if (percentMode)
398 {
399 if (c != 0)
400 return false;
401 mu.IsPercent = true;
402 mu.Val = number;
403 return true;
404 }
405
406 if (c == 0)
407 {
408 mu.Val = number;
409 return true;
410 }
411
412 c = MyCharLower_Ascii(c);
413
414 const wchar_t c1 = end[1];
415
416 if (c == '%')
417 {
418 if (c1 != 0)
419 return false;
420 mu.IsPercent = true;
421 mu.Val = number;
422 return true;
423 }
424
425 if (c == 'b')
426 {
427 if (c1 != 0)
428 return false;
429 mu.Val = number;
430 return true;
431 }
432
433 if (c1 != 0)
434 if (MyCharLower_Ascii(c1) != 'b' || end[2] != 0)
435 return false;
436
437 unsigned numBits;
438 switch (c)
439 {
440 case 'k': numBits = 10; break;
441 case 'm': numBits = 20; break;
442 case 'g': numBits = 30; break;
443 case 't': numBits = 40; break;
444 default: return false;
445 }
446 if (number >= ((UInt64)1 << (64 - numBits)))
447 return false;
448 mu.Val = number << numBits;
449 return true;
450 }
451
452
Parse(const UString & s)453 void CMemUse::Parse(const UString &s)
454 {
455 IsDefined = ParseMemUse(s, *this);
456 }
457
458 /*
459 void MemLimit_Save(const UString &s)
460 {
461 CS_LOCK
462 CKey key;
463 CreateMainKey(key, kKeyName);
464 SetRegString(key, kMemUse, s);
465 }
466
467 bool MemLimit_Load(NCompression::CMemUse &mu)
468 {
469 mu.Clear();
470 UString a;
471 {
472 CS_LOCK
473 CKey key;
474 if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
475 return false;
476 if (key.QueryValue(kMemUse, a) != ERROR_SUCCESS)
477 return false;
478 }
479 if (a.IsEmpty())
480 return false;
481 mu.Parse(a);
482 return mu.IsDefined;
483 }
484 */
485
486 }
487
488 static LPCTSTR const kOptionsInfoKeyName = TEXT("Options");
489
490 namespace NWorkDir
491 {
492 static LPCTSTR const kWorkDirType = TEXT("WorkDirType");
493 static LPCWSTR const kWorkDirPath = L"WorkDirPath";
494 static LPCTSTR const kTempRemovableOnly = TEXT("TempRemovableOnly");
495
496
Save() const497 void CInfo::Save()const
498 {
499 CS_LOCK
500 CKey key;
501 CreateMainKey(key, kOptionsInfoKeyName);
502 key.SetValue(kWorkDirType, (UInt32)Mode);
503 key.SetValue(kWorkDirPath, fs2us(Path));
504 key.SetValue(kTempRemovableOnly, ForRemovableOnly);
505 }
506
Load()507 void CInfo::Load()
508 {
509 SetDefault();
510
511 CS_LOCK
512 CKey key;
513 if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS)
514 return;
515
516 UInt32 dirType;
517 if (key.GetValue_UInt32_IfOk(kWorkDirType, dirType) != ERROR_SUCCESS)
518 return;
519 switch (dirType)
520 {
521 case NMode::kSystem:
522 case NMode::kCurrent:
523 case NMode::kSpecified:
524 Mode = (NMode::EEnum)dirType;
525 }
526 UString pathU;
527 if (key.QueryValue(kWorkDirPath, pathU) == ERROR_SUCCESS)
528 Path = us2fs(pathU);
529 else
530 {
531 Path.Empty();
532 if (Mode == NMode::kSpecified)
533 Mode = NMode::kSystem;
534 }
535 key.GetValue_bool_IfOk(kTempRemovableOnly, ForRemovableOnly);
536 }
537
538 }
539
540 static LPCTSTR const kCascadedMenu = TEXT("CascadedMenu");
541 static LPCTSTR const kContextMenu = TEXT("ContextMenu");
542 static LPCTSTR const kMenuIcons = TEXT("MenuIcons");
543 static LPCTSTR const kElimDup = TEXT("ElimDupExtract");
544 static LPCTSTR const kWriteZoneId = TEXT("WriteZoneIdExtract");
545
Save() const546 void CContextMenuInfo::Save() const
547 {
548 CS_LOCK
549 CKey key;
550 CreateMainKey(key, kOptionsInfoKeyName);
551
552 Key_Set_BoolPair(key, kCascadedMenu, Cascaded);
553 Key_Set_BoolPair(key, kMenuIcons, MenuIcons);
554 Key_Set_BoolPair(key, kElimDup, ElimDup);
555
556 Key_Set_UInt32(key, kWriteZoneId, WriteZone);
557
558 if (Flags_Def)
559 key.SetValue(kContextMenu, Flags);
560 }
561
Load()562 void CContextMenuInfo::Load()
563 {
564 Cascaded.Val = true;
565 Cascaded.Def = false;
566
567 MenuIcons.Val = false;
568 MenuIcons.Def = false;
569
570 ElimDup.Val = true;
571 ElimDup.Def = false;
572
573 WriteZone = (UInt32)(Int32)-1;
574
575 /* we can disable email items by default,
576 because email code doesn't work in some systems */
577 Flags = (UInt32)(Int32)-1
578 /*
579 & ~NContextMenuFlags::kCompressEmail
580 & ~NContextMenuFlags::kCompressTo7zEmail
581 & ~NContextMenuFlags::kCompressToZipEmail
582 */
583 ;
584 Flags_Def = false;
585
586 CS_LOCK
587
588 CKey key;
589 if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS)
590 return;
591
592 Key_Get_BoolPair_true(key, kCascadedMenu, Cascaded);
593 Key_Get_BoolPair_true(key, kElimDup, ElimDup);
594 Key_Get_BoolPair(key, kMenuIcons, MenuIcons);
595
596 Key_Get_UInt32(key, kWriteZoneId, WriteZone);
597
598 Flags_Def = (key.GetValue_UInt32_IfOk(kContextMenu, Flags) == ERROR_SUCCESS);
599 }
600