Преглед изворни кода

/LOG: Now logs more uninstaller actions.

Martijn Laan пре 4 година
родитељ
комит
1f0f1fba6f
2 измењених фајлова са 85 додато и 46 уклоњено
  1. 84 46
      Projects/Undo.pas
  2. 1 0
      whatsnew.htm

+ 84 - 46
Projects/Undo.pas

@@ -250,7 +250,7 @@ begin
   Result := False;
 end;
 
-procedure RestartDeleteDir(const DisableFsRedir: Boolean; Dir: String);
+procedure LoggedRestartDeleteDir(const DisableFsRedir: Boolean; Dir: String);
 begin
   Dir := PathExpand(Dir);
   if not DisableFsRedir then begin
@@ -267,7 +267,7 @@ const
   drFalse = '0';
   drTrue = '1';
 
-function DeleteDir(const DisableFsRedir: Boolean; const DirName: String;
+function LoggedDeleteDir(const DisableFsRedir: Boolean; const DirName: String;
   const DirsNotRemoved, RestartDeleteDirList: TSimpleStringList): Boolean;
 const
   FILE_ATTRIBUTE_REPARSE_POINT = $00000400;
@@ -307,7 +307,7 @@ begin
           restart-delete directories on Windows 9x. }
         LogFmt('Failed to delete directory (%d). Will delete on restart (if empty).',
           [LastError]);
-        RestartDeleteDir(DisableFsRedir, DirName);
+        LoggedRestartDeleteDir(DisableFsRedir, DirName);
       end
       else
         LogFmt('Failed to delete directory (%d).', [LastError]);
@@ -483,13 +483,13 @@ type
     DirsNotRemoved: TSimpleStringList;
   end;
 
-function DeleteDirProc(const DisableFsRedir: Boolean; const DirName: String;
+function LoggedDeleteDirProc(const DisableFsRedir: Boolean; const DirName: String;
   const Param: Pointer): Boolean;
 begin
-  Result := DeleteDir(DisableFsRedir, DirName, PDeleteDirData(Param)^.DirsNotRemoved, nil);
+  Result := LoggedDeleteDir(DisableFsRedir, DirName, PDeleteDirData(Param)^.DirsNotRemoved, nil);
 end;
 
-function DeleteFileProc(const DisableFsRedir: Boolean; const FileName: String;
+function LoggedDeleteFileProc(const DisableFsRedir: Boolean; const FileName: String;
   const Param: Pointer): Boolean;
 begin
   LogFmt('Deleting file: %s', [FileName]);
@@ -601,7 +601,7 @@ var
   UnregisteredServersList, RestartDeleteDirList: array[Boolean] of TSimpleStringList;
   DeleteDirData: TDeleteDirData;
 
-  function FileDelete(const Filename: String; const DisableFsRedir,
+  function LoggedFileDelete(const Filename: String; const DisableFsRedir,
     NotifyChange, RestartDelete, RemoveReadOnly: Boolean): Boolean;
   var
     ExistingAttr, LastError: DWORD;
@@ -610,11 +610,11 @@ var
 
     { Automatically delete generated indexes associated with help files }
     if CompareText(PathExtractExt(Filename), '.hlp') = 0 then begin
-      FileDelete(PathChangeExt(Filename, '.gid'), DisableFsRedir, False, False, False);
-      FileDelete(PathChangeExt(Filename, '.fts'), DisableFsRedir, False, False, False);
+      LoggedFileDelete(PathChangeExt(Filename, '.gid'), DisableFsRedir, False, False, False);
+      LoggedFileDelete(PathChangeExt(Filename, '.fts'), DisableFsRedir, False, False, False);
     end
     else if CompareText(PathExtractExt(Filename), '.chm') = 0 then
-      FileDelete(PathChangeExt(Filename, '.chw'), DisableFsRedir, False, False, False);
+      LoggedFileDelete(PathChangeExt(Filename, '.chw'), DisableFsRedir, False, False, False);
 
     { Automatically unpin shortcuts }
     if CompareText(PathExtractExt(Filename), '.lnk') = 0 then
@@ -665,7 +665,7 @@ var
     end;
   end;
 
-  function DoDecrementSharedCount(const Filename: String;
+  function LoggedDecrementSharedCount(const Filename: String;
     const Key64Bit: Boolean): Boolean;
   const
     Bits: array[Boolean] of Integer = (32, 64);
@@ -682,7 +682,7 @@ var
       Log('Shared count reached zero.');
   end;
 
-  procedure DoUnregisterServer(const Is64Bit: Boolean; const Filename: String);
+  procedure LoggedUnregisterServer(const Is64Bit: Boolean; const Filename: String);
   begin
     { Just as an optimization, make sure we aren't unregistering
       the same file again }
@@ -703,7 +703,7 @@ var
       LogFmt('Not unregistering DLL/OCX again: %s', [Filename]);
   end;
 
-  procedure DoUnregisterTypeLibrary(const Is64Bit: Boolean;
+  procedure LoggedUnregisterTypeLibrary(const Is64Bit: Boolean;
     const Filename: String);
   begin
     if Is64Bit then
@@ -721,7 +721,7 @@ var
     end;
   end;
 
-  procedure DoUninstallAssembly(const StrongAssemblyName: String);
+  procedure LoggedUninstallAssembly(const StrongAssemblyName: String);
   begin
     LogFmt('Uninstalling from GAC: %s', [StrongAssemblyName]);
     try
@@ -735,7 +735,7 @@ var
     end;
   end;
 
-  procedure ProcessDirsNotRemoved;
+  procedure LoggedProcessDirsNotRemoved;
   var
     I: Integer;
     S: String;
@@ -747,9 +747,17 @@ var
         (e.g. '0C:\Program Files\My Program') }
       DisableFsRedir := (S[1] = drTrue);
       System.Delete(S, 1, 1);
-      DeleteDir(DisableFsRedir, S, nil, RestartDeleteDirList[DisableFsRedir]);
+      LoggedDeleteDir(DisableFsRedir, S, nil, RestartDeleteDirList[DisableFsRedir]);
     end;
   end;
+  
+  function GetLogIniFilename(const Filename: String): String;
+  begin
+    if Filename <> '' then
+      Result := Filename
+    else
+      Result := 'win.ini';
+  end;
 
 const
   GroupInfoChars: array[0..3] of Char = ('"', '"', ',', ',');
@@ -760,7 +768,8 @@ var
   CurRecDataPChar: array[0..9] of PChar;
   CurRecData: array[0..9] of String;
   ShouldDeleteRec, IsTempFile, IsSharedFile, SharedCountDidReachZero: Boolean;
-  FN: String;
+  Filename, Section, Key: String;
+  Subkey, ValueName: PChar;
   P, ErrorCode: Integer;
   RegView: TRegView;
   RootKey, K: HKEY;
@@ -904,7 +913,7 @@ begin
             { Decrement shared file count if necessary }
             IsSharedFile := CurRec^.ExtraData and utDeleteFile_SharedFile <> 0;
             if IsSharedFile then
-              SharedCountDidReachZero := DoDecrementSharedCount(CurRecData[0],
+              SharedCountDidReachZero := LoggedDecrementSharedCount(CurRecData[0],
                 CurRec^.ExtraData and utDeleteFile_SharedFileIn64BitKey <> 0)
             else
               SharedCountDidReachZero := False; //silence compiler
@@ -922,11 +931,11 @@ begin
               { Unregister if necessary }
               if not IsTempFile then begin
                 if CurRec^.ExtraData and utDeleteFile_RegisteredServer <> 0 then begin
-                  DoUnregisterServer(CurRec^.ExtraData and utDeleteFile_DisableFsRedir <> 0,
+                  LoggedUnregisterServer(CurRec^.ExtraData and utDeleteFile_DisableFsRedir <> 0,
                     CurRecData[0]);
                 end;
                 if CurRec^.ExtraData and utDeleteFile_RegisteredTypeLib <> 0 then begin
-                  DoUnregisterTypeLibrary(CurRec^.ExtraData and utDeleteFile_DisableFsRedir <> 0,
+                  LoggedUnregisterTypeLibrary(CurRec^.ExtraData and utDeleteFile_DisableFsRedir <> 0,
                     CurRecData[0]);
                 end;
               end;
@@ -935,7 +944,7 @@ begin
                 UnregisterFont(CurRecData[2], CurRecData[3], CurRec^.ExtraData and utDeleteFile_PerUserFont <> 0);
               end;
               if CurRec^.ExtraData and utDeleteFile_GacInstalled <> 0 then
-                DoUninstallAssembly(CurRecData[4]);
+                LoggedUninstallAssembly(CurRecData[4]);
             end;
           end
           else begin
@@ -984,7 +993,7 @@ begin
                  CurRecData[0], CurRec^.ExtraData and utDeleteDirOrFiles_IsDir <> 0,
                  CurRec^.ExtraData and utDeleteDirOrFiles_DeleteFiles <> 0,
                  CurRec^.ExtraData and utDeleteDirOrFiles_DeleteSubdirsAlso <> 0,
-                 False, DeleteDirProc, DeleteFileProc, @DeleteDirData) then begin
+                 False, LoggedDeleteDirProc, LoggedDeleteFileProc, @DeleteDirData) then begin
                 if (CurRec^.ExtraData and utDeleteDirOrFiles_IsDir <> 0) and
                    (CurRec^.ExtraData and utDeleteDirOrFiles_CallChangeNotify <> 0) then begin
                   SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, CurRecDataPChar[0], nil);
@@ -994,13 +1003,13 @@ begin
             end;
           utDeleteFile: begin
               { Note: Some of this code is duplicated in Step 2 }
-              FN := CurRecData[1];
-              if CallFromUninstaller or (FN = '') then
-                FN := CurRecData[0];
+              Filename := CurRecData[1];
+              if CallFromUninstaller or (Filename = '') then
+                Filename := CurRecData[0];
               if CallFromUninstaller or (CurRec^.ExtraData and utDeleteFile_ExistedBeforeInstall = 0) then begin
                 { Note: We handled utDeleteFile_SharedFile already }
                 if CallFromUninstaller or (CurRec^.ExtraData and utDeleteFile_Extra = 0) then
-                  if not FileDelete(FN, CurRec^.ExtraData and utDeleteFile_DisableFsRedir <> 0,
+                  if not LoggedFileDelete(Filename, CurRec^.ExtraData and utDeleteFile_DisableFsRedir <> 0,
                      CurRec^.ExtraData and utDeleteFile_CallChangeNotify <> 0,
                      CurRec^.ExtraData and utDeleteFile_RestartDelete <> 0,
                      CurRec^.ExtraData and utDeleteFile_RemoveReadOnly <> 0) then
@@ -1010,11 +1019,11 @@ begin
                 { We're running from Setup, and the file existed before
                   installation... }
                 if CurRec^.ExtraData and utDeleteFile_SharedFile <> 0 then
-                  DoDecrementSharedCount(CurRecData[0],
+                  LoggedDecrementSharedCount(CurRecData[0],
                     CurRec^.ExtraData and utDeleteFile_SharedFileIn64BitKey <> 0);
                 { Delete file only if it's a temp file }
-                if FN <> CurRecData[0] then
-                  if not FileDelete(FN, CurRec^.ExtraData and utDeleteFile_DisableFsRedir <> 0,
+                if Filename <> CurRecData[0] then
+                  if not LoggedFileDelete(Filename, CurRec^.ExtraData and utDeleteFile_DisableFsRedir <> 0,
                      CurRec^.ExtraData and utDeleteFile_CallChangeNotify <> 0,
                      CurRec^.ExtraData and utDeleteFile_RestartDelete <> 0,
                      CurRec^.ExtraData and utDeleteFile_RemoveReadOnly <> 0) then
@@ -1023,46 +1032,75 @@ begin
             end;
           utDeleteGroupOrItem: ;   { dummy - no longer supported }
           utIniDeleteEntry: begin
-              DeleteIniEntry(CurRecData[1], CurRecData[2], CurRecData[0]); 
+              Section := CurRecData[1];
+              Key := CurRecData[2];
+              Filename := CurRecData[0];
+              LogFmt('Deleting INI entry: %s in section %s in %s', [Key, Section, GetLogIniFilename(Filename)]);
+              DeleteIniEntry(Section, Key, Filename);
             end;
           utIniDeleteSection: begin
+              Section := CurRecData[1];
+              Filename := CurRecData[0];
               if (CurRec^.ExtraData and utIniDeleteSection_OnlyIfEmpty = 0) or
-                 IsIniSectionEmpty(CurRecData[1], CurRecData[0]) then
-                DeleteIniSection(CurRecData[1], CurRecData[0]);
+                 IsIniSectionEmpty(Section, Filename) then begin
+                LogFmt('Deleting INI section: %s in %s', [Section, GetLogIniFilename(Filename)]);
+                DeleteIniSection(Section, Filename);
+              end;
             end;
           utRegDeleteEntireKey: begin
               CrackRegExtraData(CurRec^.ExtraData, RegView, RootKey);
-              if not (RegDeleteKeyIncludingSubkeys(RegView, RootKey, CurRecDataPChar[0]) in
-                 [ERROR_SUCCESS, ERROR_FILE_NOT_FOUND]) then
+              Subkey := CurRecDataPChar[0];
+              LogFmt('Deleting registry key: %s\%s', [GetRegRootKeyName(RootKey), Subkey]);
+              ErrorCode := RegDeleteKeyIncludingSubkeys(RegView, RootKey, Subkey);
+              if not (ErrorCode in [ERROR_SUCCESS, ERROR_FILE_NOT_FOUND]) then begin
+                LogFmt('Deletion failed (%d).', [ErrorCode]);
                 Result := False;
+              end;
             end;
           utRegClearValue: begin
               CrackRegExtraData(CurRec^.ExtraData, RegView, RootKey);
-              if RegOpenKeyExView(RegView, RootKey, CurRecDataPChar[0], 0, KEY_SET_VALUE, K) = ERROR_SUCCESS then begin
-                if RegSetValueEx(K, CurRecDataPChar[1], 0, REG_SZ, @NullChar,
-                   SizeOf(NullChar)) <> ERROR_SUCCESS then
+              Subkey := CurRecDataPChar[0];
+              ValueName := CurRecDataPChar[1];
+              LogFmt('Clearing registry value: %s\%s\%s', [GetRegRootKeyName(RootKey), Subkey, ValueName]);
+              if RegOpenKeyExView(RegView, RootKey, Subkey, 0, KEY_SET_VALUE, K) = ERROR_SUCCESS then begin
+                ErrorCode := RegSetValueEx(K, ValueName, 0, REG_SZ, @NullChar, SizeOf(NullChar));
+                if ErrorCode <> ERROR_SUCCESS then begin
+                  LogFmt('RegSetValueEx failed (%d).', [ErrorCode]);
                   Result := False;
+                end;
                 RegCloseKey(K);
               end;
             end;
           utRegDeleteKeyIfEmpty: begin
               CrackRegExtraData(CurRec^.ExtraData, RegView, RootKey);
-              if not (RegDeleteKeyIfEmpty(RegView, RootKey, CurRecDataPChar[0]) in
-                 [ERROR_SUCCESS, ERROR_FILE_NOT_FOUND, ERROR_DIR_NOT_EMPTY]) then
+              Subkey := CurRecDataPChar[0];
+              LogFmt('Deleting empty registry key: %s\%s', [GetRegRootKeyName(RootKey), Subkey]);
+              ErrorCode := RegDeleteKeyIfEmpty(RegView, RootKey, Subkey);
+              if ErrorCode = ERROR_DIR_NOT_EMPTY then
+                Log('Deletion skipped (not empty).')
+              else if not (ErrorCode in [ERROR_SUCCESS, ERROR_FILE_NOT_FOUND]) then begin
+                LogFmt('Deletion failed (%d).', [ErrorCode]);
                 Result := False;
+              end;
             end;
           utRegDeleteValue: begin
               CrackRegExtraData(CurRec^.ExtraData, RegView, RootKey);
-              if RegOpenKeyExView(RegView, RootKey, CurRecDataPChar[0], 0,
-                 KEY_QUERY_VALUE or KEY_SET_VALUE, K) = ERROR_SUCCESS then begin
-                if RegValueExists(K, CurRecDataPChar[1]) and
-                   (RegDeleteValue(K, CurRecDataPChar[1]) <> ERROR_SUCCESS) then
-                  Result := False;
+              Subkey := CurRecDataPChar[0];
+              ValueName := CurRecDataPChar[1];
+              LogFmt('Deleting registry value: %s\%s\%s', [GetRegRootKeyName(RootKey), Subkey, ValueName]);
+              if RegOpenKeyExView(RegView, RootKey, Subkey, 0, KEY_QUERY_VALUE or KEY_SET_VALUE, K) = ERROR_SUCCESS then begin
+                if RegValueExists(K, ValueName) then begin
+                  ErrorCode := RegDeleteValue(K, ValueName);
+                  if ErrorCode <> ERROR_SUCCESS then begin
+                    LogFmt('RegDeleteValue failed (%d).', [ErrorCode]);
+                    Result := False;
+                  end;
+                end;
                 RegCloseKey(K);
               end;
             end;
           utDecrementSharedCount: begin
-              DoDecrementSharedCount(CurRecData[0],
+              LoggedDecrementSharedCount(CurRecData[0],
                 CurRec^.ExtraData and utDecrementSharedCount_64BitKey <> 0);
             end;
           utRefreshFileAssoc:
@@ -1089,7 +1127,7 @@ begin
       DeleteUninstallDataFilesProc;
       { Now that uninstall data is deleted, try removing the directories it
         was in that couldn't be deleted before. }
-      ProcessDirsNotRemoved;
+      LoggedProcessDirsNotRemoved;
     end;
   finally
     DeleteDirData.DirsNotRemoved.Free;

+ 1 - 0
whatsnew.htm

@@ -30,6 +30,7 @@ For conditions of distribution and use, see <a href="https://jrsoftware.org/file
 
 <p><a name="6.1.3"></a><span class="ver">6.1.3-dev </span><span class="date">(?)</span></p>
 <ul>
+  <li>/LOG: Now logs more uninstaller actions.</li>
   <li>Compiler IDE change: <i>Fix:</i> Autocomplete support for event functions listed some procedures as functions.</li>
   <li>Pascal Scripting changes:
   <ul>