Rev 1 | Go to most recent revision | 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. |