瀏覽代碼

When cleaning up application data, deleting even Martin Prikryl and WinSCP 2 root keys, if they remain empty

Source commit: 59d177a9304cb8d627e2c2c967b7d9f725753114
Martin Prikryl 1 年之前
父節點
當前提交
4cf1ac20db
共有 3 個文件被更改,包括 103 次插入33 次删除
  1. 39 8
      source/core/Configuration.cpp
  2. 56 21
      source/core/HierarchicalStorage.cpp
  3. 8 4
      source/core/HierarchicalStorage.h

+ 39 - 8
source/core/Configuration.cpp

@@ -939,14 +939,45 @@ bool TConfiguration::RegistryPathExists(const UnicodeString & RegistryPath)
 //---------------------------------------------------------------------------
 void __fastcall TConfiguration::CleanupRegistry(const UnicodeString & RegistryPath)
 {
-  std::unique_ptr<TRegistryStorage> Registry(new TRegistryStorage(RegistryStorageKey));
-
-  UnicodeString ParentKey = ExtractFileDir(RegistryPath);
-  if (ParentKey.IsEmpty() ||
-      Registry->OpenSubKeyPath(ParentKey, false))
-  {
-    UnicodeString SubKey = ExtractFileName(RegistryPath);
-    Registry->RecursiveDeleteSubKey(SubKey);
+  UnicodeString CompanyKey = GetCompanyRegistryKey();
+  UnicodeString Prefix = IncludeTrailingBackslash(CompanyKey);
+  if (DebugAlwaysTrue(SameStr(LeftStr(RegistryStorageKey, Prefix.Length()), Prefix)))
+  {
+    UnicodeString CompanyParentKey = ExtractFileDir(CompanyKey);
+    std::unique_ptr<TRegistryStorage> Registry(new TRegistryStorage(CompanyParentKey));
+    UnicodeString RegistryStorageSubKey = MidStr(RegistryStorageKey, CompanyParentKey.Length() + 2);
+    Registry->UnmungedRoot = RegistryStorageSubKey;
+
+    AppLogFmt(L"Cleaning up registry key %s", (RegistryPath));
+    UnicodeString ARegistryPath = TPath::Combine(RegistryStorageSubKey, RegistryPath);
+    UnicodeString Buf = ARegistryPath;
+    while (!Buf.IsEmpty())
+    {
+      UnicodeString ParentKey = ExtractFileDir(Buf);
+      // Actually can be simplified to Registry->OpenSubKeyPath(ParentKey, false)
+      if (ParentKey.IsEmpty() ? Registry->OpenRootKey(false) : Registry->OpenSubKeyPath(ParentKey, false))
+      {
+        UnicodeString SubKey = ExtractFileName(Buf);
+        if (Registry->KeyExists(SubKey))
+        {
+          bool Recursive = (Buf == ARegistryPath);
+          if (Registry->DeleteSubKey(SubKey, Recursive))
+          {
+            AppLogFmt(L"Deleted registry key %s in %s", (SubKey, ParentKey));
+          }
+          else
+          {
+            break;
+          }
+        }
+        Registry->CloseSubKeyPath();
+        Buf = ParentKey;
+      }
+      else
+      {
+        break;
+      }
+    }
   }
 }
 //---------------------------------------------------------------------------

+ 56 - 21
source/core/HierarchicalStorage.cpp

@@ -210,13 +210,27 @@ bool __fastcall THierarchicalStorage::OpenRootKey(bool CanCreate)
   return OpenSubKey(UnicodeString(), CanCreate);
 }
 //---------------------------------------------------------------------------
+bool THierarchicalStorage::MungingKeyName(const UnicodeString & Key)
+{
+  UnicodeString K = CurrentSubKey + Key + L"\\";
+  return UnmungedRoot.IsEmpty() || !SameText(LeftStr(UnmungedRoot + L"\\", K.Length()), K);
+}
+//---------------------------------------------------------------------------
 UnicodeString __fastcall THierarchicalStorage::MungeKeyName(const UnicodeString & Key)
 {
-  UnicodeString Result = MungeStr(Key, ForceAnsi, false);
-  // if there's already ANSI-munged subkey, keep ANSI munging
-  if ((Result != Key) && !ForceAnsi && CanRead() && DoKeyExists(Key, true))
+  UnicodeString Result;
+  if (!MungingKeyName(Key))
   {
-    Result = MungeStr(Key, true, false);
+    Result = Key;
+  }
+  else
+  {
+    Result = MungeStr(Key, ForceAnsi, false);
+    // if there's already ANSI-munged subkey, keep ANSI munging
+    if ((Result != Key) && !ForceAnsi && CanRead() && DoKeyExists(Key, true))
+    {
+      Result = MungeStr(Key, true, false);
+    }
   }
   return Result;
 }
@@ -415,30 +429,46 @@ void __fastcall THierarchicalStorage::ClearSubKeys()
   }
 }
 //---------------------------------------------------------------------------
-void __fastcall THierarchicalStorage::RecursiveDeleteSubKey(const UnicodeString & Key)
+bool THierarchicalStorage::RecursiveDeleteSubKey(const UnicodeString & Key)
+{
+  return DeleteSubKey(Key, true);
+}
+//---------------------------------------------------------------------------
+bool THierarchicalStorage::DeleteSubKey(const UnicodeString & Key, bool Recursive)
 {
   bool CanWriteParent = CanWrite();
-  if (OpenSubKey(Key, false))
+  bool Result = OpenSubKey(Key, false);
+  if (Result)
   {
-    ClearSubKeys();
+    if (Recursive)
+    {
+      ClearSubKeys();
 
-    // Cannot delete the key itself, but can delete its contents, so at least delete the values
-    // (which would otherwise be deleted implicitly by DoDeleteSubKey)
-    if (!CanWriteParent && CanWrite())
+      // Cannot delete the key itself, but can delete its contents, so at least delete the values
+      // (which would otherwise be deleted implicitly by DoDeleteSubKey)
+      if (!CanWriteParent && CanWrite())
+      {
+        ClearValues();
+      }
+    }
+
+    std::unique_ptr<TStrings> ValueNames(new TStringList());
+    if (!Recursive)
     {
-      ClearValues();
+      GetValueNames(ValueNames.get());
     }
 
     // Only if all subkeys were successfully deleted in ClearSubKeys
-    bool Delete = CanWriteParent && !HasSubKeys();
+    Result = CanWriteParent && !HasSubKeys() && (ValueNames->Count == 0);
 
     CloseSubKey();
 
-    if (Delete)
+    if (Result)
     {
-      DoDeleteSubKey(Key);
+      Result = DoDeleteSubKey(Key);
     }
   }
+  return Result;
 }
 //---------------------------------------------------------------------------
 bool __fastcall THierarchicalStorage::HasSubKeys()
@@ -958,7 +988,7 @@ void __fastcall TRegistryStorage::DoCloseSubKey()
   }
 }
 //---------------------------------------------------------------------------
-void __fastcall TRegistryStorage::DoDeleteSubKey(const UnicodeString & SubKey)
+bool __fastcall TRegistryStorage::DoDeleteSubKey(const UnicodeString & SubKey)
 {
   UnicodeString K;
   if (FKeyHistory.empty())
@@ -966,7 +996,7 @@ void __fastcall TRegistryStorage::DoDeleteSubKey(const UnicodeString & SubKey)
     K = Storage + CurrentSubKey;
   }
   K += MungeKeyName(SubKey);
-  FRegistry->DeleteKey(K);
+  return FRegistry->DeleteKey(K);
 }
 //---------------------------------------------------------------------------
 void __fastcall TRegistryStorage::DoGetSubKeyNames(TStrings * Strings)
@@ -990,7 +1020,11 @@ bool __fastcall TRegistryStorage::DoDeleteValue(const UnicodeString & Name)
 //---------------------------------------------------------------------------
 bool __fastcall TRegistryStorage::DoKeyExists(const UnicodeString & SubKey, bool AForceAnsi)
 {
-  UnicodeString K = MungeStr(SubKey, AForceAnsi, false);
+  UnicodeString K = SubKey;
+  if (MungingKeyName(K))
+  {
+    K = MungeStr(K, AForceAnsi, false);
+  }
   bool Result = FRegistry->KeyExists(K);
   return Result;
 }
@@ -1233,8 +1267,9 @@ void __fastcall TCustomIniFileStorage::CloseSubKey()
   THierarchicalStorage::CloseSubKey();
 }
 //---------------------------------------------------------------------------
-void __fastcall TCustomIniFileStorage::DoDeleteSubKey(const UnicodeString & SubKey)
+bool __fastcall TCustomIniFileStorage::DoDeleteSubKey(const UnicodeString & SubKey)
 {
+  bool Result = true;
   try
   {
     ResetCache();
@@ -1245,11 +1280,11 @@ void __fastcall TCustomIniFileStorage::DoDeleteSubKey(const UnicodeString & SubK
   }
   if (HandleByMasterStorage())
   {
-    if (FMasterStorage->CanWrite())
-    {
+    Result =
+      FMasterStorage->CanWrite() &&
       FMasterStorage->DoDeleteSubKey(SubKey);
-    }
   }
+  return Result;
 }
 //---------------------------------------------------------------------------
 void __fastcall TCustomIniFileStorage::DoGetSubKeyNames(TStrings * Strings)

+ 8 - 4
source/core/HierarchicalStorage.h

@@ -29,7 +29,8 @@ public:
   bool __fastcall HasSubKeys();
   bool __fastcall KeyExists(const UnicodeString & SubKey);
   bool __fastcall ValueExists(const UnicodeString & Value);
-  virtual void __fastcall RecursiveDeleteSubKey(const UnicodeString & Key);
+  bool DeleteSubKey(const UnicodeString & Key, bool Recursive = false);
+  bool RecursiveDeleteSubKey(const UnicodeString & Key);
   virtual void __fastcall ClearSubKeys();
   virtual void __fastcall ReadValues(TStrings* Strings, bool MaintainKeys = false);
   virtual void __fastcall WriteValues(TStrings* Strings, bool MaintainKeys = false);
@@ -72,6 +73,7 @@ public:
   __property bool MungeStringValues = { read = FMungeStringValues, write = FMungeStringValues };
   __property UnicodeString Source = { read = GetSource };
   __property bool Temporary = { read = GetTemporary };
+  __property UnicodeString UnmungedRoot = { read = FUnmungedRoot, write = FUnmungedRoot };
 
 protected:
   enum THierarchicalStorageAccess { hsaRead = 0x01, hsaWrite = 0x02 };
@@ -91,6 +93,7 @@ protected:
   bool FForceAnsi;
   int FFakeReadOnlyOpens;
   int FRootAccess;
+  UnicodeString FUnmungedRoot;
 
   __property bool ForceAnsi = { read = FForceAnsi, write = FForceAnsi };
 
@@ -103,10 +106,11 @@ protected:
   static UnicodeString __fastcall ExcludeTrailingBackslash(const UnicodeString & S);
   virtual bool __fastcall DoOpenSubKey(const UnicodeString & SubKey, bool CanCreate) = 0;
   virtual void __fastcall DoCloseSubKey() = 0;
+  bool MungingKeyName(const UnicodeString & Key);
   UnicodeString __fastcall MungeKeyName(const UnicodeString & Key);
   virtual UnicodeString __fastcall GetSource() = 0;
   virtual bool __fastcall GetTemporary();
-  virtual void __fastcall DoDeleteSubKey(const UnicodeString & SubKey) = 0;
+  virtual bool __fastcall DoDeleteSubKey(const UnicodeString & SubKey) = 0;
   virtual bool __fastcall DoDeleteValue(const UnicodeString & Name) = 0;
 
   virtual void __fastcall DoGetSubKeyNames(TStrings * Strings) = 0;
@@ -167,7 +171,7 @@ protected:
   virtual void __fastcall DoCloseSubKey();
   virtual UnicodeString __fastcall GetSource();
   virtual size_t __fastcall DoBinaryDataSize(const UnicodeString & Name);
-  virtual void __fastcall DoDeleteSubKey(const UnicodeString & SubKey);
+  virtual bool __fastcall DoDeleteSubKey(const UnicodeString & SubKey);
   virtual bool __fastcall DoDeleteValue(const UnicodeString & Name);
 
   virtual void __fastcall DoGetSubKeyNames(TStrings * Strings);
@@ -226,7 +230,7 @@ protected:
   virtual void __fastcall DoCloseSubKey();
   virtual UnicodeString __fastcall GetSource();
   virtual size_t __fastcall DoBinaryDataSize(const UnicodeString & Name);
-  virtual void __fastcall DoDeleteSubKey(const UnicodeString & SubKey);
+  virtual bool __fastcall DoDeleteSubKey(const UnicodeString & SubKey);
   virtual bool __fastcall DoDeleteValue(const UnicodeString & Name);
 
   virtual void __fastcall DoGetSubKeyNames(TStrings * Strings);