Subversion Repositories autosfx

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. program MakeSFX;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. {.$DEFINE BREAK_ON_CERT_FAILURE}
  6. {$DEFINE DELAY_ON_ERROR}
  7.  
  8. uses
  9.   SysUtils,
  10.   Windows,
  11.   Classes,
  12.   ZipMstr19,
  13.   Functions in 'Functions.pas',
  14.   SFXBehavior in 'SFXBehavior.pas';
  15.  
  16. const
  17.   Extractor_EXE = 'Extractor.exe';
  18.   SIGN_BAT = 'Tools\VTSSign.bat';
  19.   ZIP_EXE = 'Tools\zip.exe';
  20.   RemoveSignature_EXE = 'Tools\RemoveSignature.exe';
  21.  
  22. var
  23.   Src, Dst: string;
  24.   i: integer;
  25.   s1, s2: TFileStream;
  26.   x: TZipMaster19;
  27.  
  28. resourcestring
  29.   ImportantFileNotFound = 'Error: Important file "%s" not found!';
  30.   LngErrorWhileCopy = 'Error: Could not copy "%s" to "%s".';
  31.   LngErrorWhileExecuting = 'Error while executing "%s".';
  32.   SourceFileNotFound = 'Source file "%s" not found.';
  33.   Lng_In = 'Input:';
  34.   Lng_Out = 'Output:';
  35.   Lng_RemoveSig = 'Remove signature of Extractor template...';
  36.   Lng_Append = 'Append ZIP to Extractor template...';
  37.   Lng_Adjust = 'Adjust the ZIP offset of the SFX...';
  38.   Lng_ModifyZIPComment = 'Modify ZIP Comment...';
  39.   Lng_SignSfx = 'Sign the SFX...';
  40.   Lng_Finished = 'Finished! :-)';
  41.   Lng_Title = 'ViaThinkSoft AutoSFX';
  42.   Lng_Usage1 = 'Usage:';
  43.   Lng_Usage2 = 'MakeSFX [File1.zip [File2.zip...]]';
  44.  
  45. {$R *.res}
  46.  
  47. begin
  48.   WriteLn(Lng_Title);
  49.   WriteLn('');
  50.   WriteLn(Lng_Usage1);
  51.   WriteLn(Lng_Usage2);
  52.   WriteLn('');
  53.  
  54.   if not FileExists(ExtractFilePath(ParamStr(0)) + Extractor_EXE) then
  55.   begin
  56.     WriteLn(Format(ImportantFileNotFound, [Extractor_EXE]));
  57.     {$IFDEF DELAY_ON_ERROR}
  58.     Sleep(2000);
  59.     {$ENDIF}
  60.     ExitCode := 2;
  61.     Exit;
  62.   end;
  63.  
  64.   for i := 1 to ParamCount do
  65.   begin
  66.     Src := ParamStr(i);
  67.  
  68.     if not FileExists(Src) then
  69.     begin
  70.       WriteLn(Format(SourceFileNotFound, [Src]));
  71.       {$IFDEF DELAY_ON_ERROR}
  72.       Sleep(2000);
  73.       {$ENDIF}
  74.       ExitCode := 1;
  75.       Continue;
  76.     end;
  77.  
  78.     Dst := ChangeFileExt(Src, '.exe');
  79.  
  80.     WriteLn(Format(Lng_In+#9+'%s', [Src]));
  81.     WriteLn(Format(Lng_Out+#9+'%s', [Dst]));
  82.     WriteLn('');
  83.  
  84.     if not RawFileCopy(ExtractFilePath(ParamStr(0)) + Extractor_EXE, Dst) then
  85.     begin
  86.       WriteLn(Format(LngErrorWhileCopy, [Extractor_EXE, Dst]));
  87.       {$IFDEF DELAY_ON_ERROR}
  88.       Sleep(2000);
  89.       {$ENDIF}
  90.       ExitCode := 1;
  91.       Continue;
  92.     end;
  93.  
  94.    // Remove the signature of Extractor first (otherwise signing will fail later)
  95.  
  96.     WriteLn(#9 + Lng_RemoveSig);
  97.  
  98.     if not ShellExecuteAndWait(ExtractFilePath(ParamStr(0)) + RemoveSignature_EXE, PChar('"' + ExpandUNCFileName(Dst) + '"')) then
  99.     begin
  100.       WriteLn(Format(LngErrorWhileExecuting, [RemoveSignature_EXE]));
  101.       {$IFDEF BREAK_ON_CERT_FAILURE}
  102.       DeleteFile(PChar(Dst));
  103.       {$IFDEF DELAY_ON_ERROR}
  104.       Sleep(2000);
  105.       {$ENDIF}
  106.       ExitCode := 1;
  107.       Continue;
  108.       {$ENDIF}
  109.     end;
  110.  
  111.     WriteLn(#9 + Lng_Append);
  112.  
  113.     s1 := TFileStream.Create(Dst, fmOpenWrite);
  114.     try
  115.       s1.Seek(0, soEnd);
  116.  
  117.       s2 := TFileStream.Create(Src, fmOpenRead or fmShareDenyWrite);
  118.       try
  119.         s1.CopyFrom(s2, s2.Size);
  120.       finally
  121.         s2.Free;
  122.       end;
  123.     finally
  124.       s1.Free;
  125.     end;
  126.  
  127.     WriteLn(#9 + Lng_Adjust);
  128.  
  129.     if not ShellExecuteAndWait(ExtractFilePath(ParamStr(0)) + ZIP_EXE, PChar('-A "' + ExpandUNCFileName(Dst) + '"')) then
  130.     begin
  131.       DeleteFile(PChar(Dst));
  132.       WriteLn(Format(LngErrorWhileExecuting, [ZIP_EXE]));
  133.       {$IFDEF DELAY_ON_ERROR}
  134.       Sleep(2000);
  135.       {$ENDIF}
  136.       ExitCode := 1;
  137.       Continue;
  138.     end;
  139.  
  140.     WriteLn(#9 + Lng_ModifyZIPComment);
  141.  
  142.     x := TZipMaster19.Create(nil);
  143.     try
  144.       x.ZipFileName := Dst;
  145.  
  146.       // Correct CRLFs
  147.  
  148.       x.ZipComment := NormalizeLineBreaks(x.ZipComment, lbWindows);
  149.  
  150.       // Ensure we have 2 CRLF before old comment
  151.  
  152.       x.ZipComment := TrimRight(x.ZipComment);
  153.       if x.ZipComment <> '' then
  154.       begin
  155.         x.ZipComment := x.ZipComment + #13#10 + #13#10;
  156.       end;
  157.  
  158.       // Read, strip and re-add behavior (inclusive signature)
  159.  
  160.       x.ZipComment := RelocateBehaviorStringsToEnd(x.ZipComment);
  161.     finally
  162.       x.Free;
  163.     end;
  164.  
  165.     // Read filesize + zip-comment length
  166.     // (So we can later extend the zip-comment to include the certificate
  167.     // => The archive is then not corrupt because of 'garbage' at the end)
  168.  
  169.     WriteLn(#9 + Lng_SignSfx);
  170.  
  171.     if not ShellExecuteAndWait(ExtractFilePath(ParamStr(0)) + SIGN_BAT, PChar('"' + ExpandUNCFileName(Dst) + '"')) then
  172.     begin
  173.       WriteLn(Format(LngErrorWhileExecuting, [SIGN_BAT]));
  174.       {$IFDEF BREAK_ON_CERT_FAILURE}
  175.       DeleteFile(PChar(Dst));
  176.       {$IFDEF DELAY_ON_ERROR}
  177.       Sleep(2000);
  178.       {$ENDIF}
  179.       ExitCode := 1;
  180.       Continue;
  181.       {$ENDIF}
  182.     end;
  183.  
  184.     WriteLn(#9 + Lng_Finished);
  185.     WriteLn('');
  186.   end;
  187.  
  188.   // TODO: Es gibt bei Win2000 außerhalb des debuggers eine AV...
  189. end.
  190.