Subversion Repositories autosfx

Rev

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