Subversion Repositories autosfx

Rev

Rev 1 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 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,
4 daniel-mar 13
  Dialogs,
1 daniel-mar 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
 
4 daniel-mar 23
procedure DoMakeSFX(AFilename: string);
1 daniel-mar 24
var
4 daniel-mar 25
  Dst: string;
1 daniel-mar 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! :-)';
4 daniel-mar 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;
1 daniel-mar 50
 
4 daniel-mar 51
  Dst := ChangeFileExt(AFilename, '.exe');
1 daniel-mar 52
 
4 daniel-mar 53
  WriteLn(Format(Lng_In+#9+'%s', [AFilename]));
54
  WriteLn(Format(Lng_Out+#9+'%s', [Dst]));
1 daniel-mar 55
  WriteLn('');
56
 
4 daniel-mar 57
  if not RawFileCopy(ExtractFilePath(ParamStr(0)) + Extractor_EXE, Dst) then
1 daniel-mar 58
  begin
4 daniel-mar 59
    WriteLn(Format(LngErrorWhileCopy, [Extractor_EXE, Dst]));
1 daniel-mar 60
    {$IFDEF DELAY_ON_ERROR}
61
    Sleep(2000);
62
    {$ENDIF}
4 daniel-mar 63
    ExitCode := 1;
1 daniel-mar 64
    Exit;
65
  end;
66
 
4 daniel-mar 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
1 daniel-mar 72
  begin
4 daniel-mar 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;
1 daniel-mar 83
 
4 daniel-mar 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;
1 daniel-mar 95
    end;
4 daniel-mar 96
  finally
97
    s1.Free;
98
  end;
1 daniel-mar 99
 
4 daniel-mar 100
  WriteLn(#9 + Lng_Adjust);
1 daniel-mar 101
 
4 daniel-mar 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;
1 daniel-mar 112
 
4 daniel-mar 113
  WriteLn(#9 + Lng_ModifyZIPComment);
1 daniel-mar 114
 
4 daniel-mar 115
  x := TZipMaster19.Create(nil);
116
  try
117
    x.ZipFileName := Dst;
1 daniel-mar 118
 
4 daniel-mar 119
    // Correct CRLFs
1 daniel-mar 120
 
4 daniel-mar 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
1 daniel-mar 127
    begin
4 daniel-mar 128
      x.ZipComment := x.ZipComment + #13#10 + #13#10;
1 daniel-mar 129
    end;
130
 
4 daniel-mar 131
    // Read, strip and re-add behavior (inclusive signature)
1 daniel-mar 132
 
4 daniel-mar 133
    x.ZipComment := RelocateBehaviorStringsToEnd(x.ZipComment);
134
  finally
135
    x.Free;
136
  end;
1 daniel-mar 137
 
4 daniel-mar 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)
1 daniel-mar 141
 
4 daniel-mar 142
  WriteLn(#9 + Lng_SignSfx);
1 daniel-mar 143
 
4 daniel-mar 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;
1 daniel-mar 156
 
4 daniel-mar 157
  WriteLn(#9 + Lng_Finished);
158
  WriteLn('');
159
end;
1 daniel-mar 160
 
4 daniel-mar 161
{$R *.res}
1 daniel-mar 162
 
4 daniel-mar 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('');
1 daniel-mar 177
 
4 daniel-mar 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;
1 daniel-mar 187
 
4 daniel-mar 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
1 daniel-mar 197
      begin
4 daniel-mar 198
        for i := 0 to od.Files.Count - 1 do
199
        begin
200
          DoMakeSFX(od.Files.Strings[i]);
201
        end;
1 daniel-mar 202
      end;
203
    finally
4 daniel-mar 204
      od.Free;
1 daniel-mar 205
    end;
4 daniel-mar 206
  end
207
  else
208
  begin
209
    for i := 1 to ParamCount do
1 daniel-mar 210
    begin
4 daniel-mar 211
      DoMakeSFX(ParamStr(i));
1 daniel-mar 212
    end;
213
  end;
214
 
215
  // TODO: Es gibt bei Win2000 außerhalb des debuggers eine AV...
216
end.