Subversion Repositories autosfx

Rev

Go to most recent revision | Details | 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,
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.