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

Improve and document self-copy/rename/exec detection by [Code].

Martijn Laan пре 1 година
родитељ
комит
3a5e802d4f
2 измењених фајлова са 15 додато и 5 уклоњено
  1. 5 1
      ISHelp/isxfunc.xml
  2. 10 4
      Projects/Src/Setup.ScriptFunc.pas

+ 5 - 1
ISHelp/isxfunc.xml

@@ -1653,6 +1653,7 @@ end;</pre></example>
 <p>The WorkingDir parameter can be an empty string, in which case it will try to extract a pathname from the Filename parameter and use that as the initial current directory for the process. If no pathname was specified in Filename, a default directory will be used.</p>
 <p>If you have a single string containing both a filename and parameters (e.g. a command line obtained from an UninstallString registry value), you need not separate them yourself; just pass <tt>'>'</tt> in the Filename parameter, and the full command line in the Params parameter. (Note that when this is done, the function's special platform-independent support for .bat and .cmd files is disabled; it simply passes the specified command line to CreateProcess without any processing.)</p>
 <p>By default, when Setup/Uninstall is running in <link topic="32vs64bitinstalls">64-bit install mode</link>, this function disables WOW64 file system redirection when calling CreateProcess. It is possible to override this by calling <link topic="isxfunc_EnableFsRedirection">EnableFsRedirection</link>.</p>
+<p>Can't be used to execute Setup itself.</p>
 <p><i>Note: compared to ISPP's Exec the ShowCmd and Wait parameters are swapped!</i></p></remarks>
         <example><pre>var
   ResultCode: Integer;
@@ -1685,7 +1686,8 @@ end;</pre></example>
         <remarks><p>TExecWait is defined as:</p>
 <p><tt>TExecWait = (ewNoWait, ewWaitUntilTerminated, ewWaitUntilIdle);</tt></p>
 <p>Note that passing a Wait value other than <tt>ewNoWait</tt> will have no effect if a new process isn't spawned (for example, if the file is opened inside an already-running instance of the program that handles the file type).</p>
-<p>Refer to the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381.aspx">system error codes on MSDN</a>.</p></remarks>
+<p>Refer to the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381.aspx">system error codes on MSDN</a>.</p>
+<p>Can't be used to execute Setup itself.</p></remarks>
         <example><pre>var
   ErrorCode: Integer;
 begin
@@ -1838,11 +1840,13 @@ end;</pre>
         <name>RenameFile</name>
         <prototype>function RenameFile(const OldName, NewName: String): Boolean;</prototype>
         <description><p>Attempts to change the name of the file or directory specified by OldFile to NewFile. If the operation succeeds, RenameFile returns True. If it cannot rename the file (for example, if a file called NewName already exists), it returns False.</p></description>
+        <remarks><p>Can't be used to rename Setup itself.</p></remarks>
       </function>
       <function>
         <name>FileCopy</name>
         <prototype>function FileCopy(const ExistingFile, NewFile: String; const FailIfExists: Boolean): Boolean;</prototype>
         <description><p>Copies ExistingFile to NewFile, preserving time stamp and file attributes.<br />If FailIfExists is True it will fail if NewFile already exists, otherwise it will overwrite it.<br />Returns True if successful, False otherwise.</p></description>
+        <remarks><p>Can't be used to copy Setup itself.</p></remarks>
       </function>
       <function>
         <name>DeleteFile</name>

+ 10 - 4
Projects/Src/Setup.ScriptFunc.pas

@@ -112,6 +112,12 @@ begin
   ScaleBaseUnitsInitialized := True;
 end;
 
+function IsSrcExe(const Filename: String): Boolean;
+begin
+  var ExpandedFilename := PathExpand(Filename);
+  Result := PathCompare(ExpandedFilename, SetupLdrOriginalFilename) = 0;
+end;
+
 {---}
 
 function ScriptDlgProc(Caller: TPSExec; Proc: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
@@ -551,7 +557,7 @@ begin
     Stack.SetBool(PStart, True);
   end else if Proc.Name = 'FILECOPY' then begin
     ExistingFilename := Stack.GetString(PStart-1);
-    if PathCompare(ExistingFilename, SetupLdrOriginalFilename) <> 0 then
+    if not IsSrcExe(ExistingFilename) then
       Stack.SetBool(PStart, CopyFileRedir(ScriptFuncDisableFsRedir,
         ExistingFilename, Stack.GetString(PStart-2), Stack.GetBool(PStart-3)))
     else
@@ -942,7 +948,7 @@ begin
         InternalError(Format('Must call "%s" function with Wait = ewWaitUntilTerminated', [Proc.Name]));
 
       Filename := Stack.GetString(PStart-1);
-      if PathCompare(Filename, SetupLdrOriginalFilename) <> 0 then begin
+      if not IsSrcExe(Filename) then begin
         { Disable windows so the user can't utilize our UI during the InstExec
           call }
         WindowDisabler := TWindowDisabler.Create;
@@ -970,7 +976,7 @@ begin
       NoUninstallFuncError(Proc.Name);
 
     Filename := Stack.GetString(PStart-2);
-    if PathCompare(Filename, SetupLdrOriginalFilename) <> 0 then begin
+    if not IsSrcExe(Filename) then begin
       { Disable windows so the user can't utilize our UI during the
         InstShellExec call }
       WindowDisabler := TWindowDisabler.Create;
@@ -1404,7 +1410,7 @@ begin
     Stack.SetString(PStart, NewFileSearch(ScriptFuncDisableFsRedir, Stack.GetString(PStart-1), Stack.GetString(PStart-2)));
   end else if Proc.Name = 'RENAMEFILE' then begin
     OldName := Stack.GetString(PStart-1);
-    if PathCompare(OldName, SetupLdrOriginalFilename) <> 0 then
+    if not IsSrcExe(OldName) then
       Stack.SetBool(PStart, MoveFileRedir(ScriptFuncDisableFsRedir, OldName, Stack.GetString(PStart-2)))
     else
       Stack.SetBool(PStart, False);