1 /*
2  * Copyright (C) 2011-2020 Daniel Scharrer
3  *
4  * This software is provided 'as-is', without any express or implied
5  * warranty.  In no event will the author(s) be held liable for any damages
6  * arising from the use of this software.
7  *
8  * Permission is granted to anyone to use this software for any purpose,
9  * including commercial applications, and to alter it and redistribute it
10  * freely, subject to the following restrictions:
11  *
12  * 1. The origin of this software must not be misrepresented; you must not
13  *    claim that you wrote the original software. If you use this software
14  *    in a product, an acknowledgment in the product documentation would be
15  *    appreciated but is not required.
16  * 2. Altered source versions must be plainly marked as such, and must not be
17  *    misrepresented as being the original software.
18  * 3. This notice may not be removed or altered from any source distribution.
19  */
20 
21 #include "setup/header.hpp"
22 
23 #include <cstdio>
24 #include <cstring>
25 
26 #include <boost/static_assert.hpp>
27 
28 #include "setup/version.hpp"
29 #include "util/load.hpp"
30 #include "util/storedenum.hpp"
31 
32 namespace setup {
33 
34 namespace {
35 
36 STORED_ENUM_MAP(stored_alpha_format, header::AlphaIgnored,
37 	header::AlphaIgnored,
38 	header::AlphaDefined,
39 	header::AlphaPremultiplied
40 );
41 
42 STORED_ENUM_MAP(stored_install_verbosity, header::NormalInstallMode,
43 	header::NormalInstallMode,
44 	header::SilentInstallMode,
45 	header::VerySilentInstallMode
46 );
47 
48 STORED_ENUM_MAP(stored_log_mode, header::AppendLog,
49 	header::AppendLog,
50 	header::NewLog,
51 	header::OverwriteLog
52 );
53 
54 STORED_ENUM_MAP(stored_setup_style, header::ClassicStyle,
55 	header::ClassicStyle,
56 	header::ModernStyle
57 );
58 
59 STORED_ENUM_MAP(stored_bool_auto_no_yes, header::Auto,
60 	header::Auto,
61 	header::No,
62 	header::Yes
63 );
64 
65 // pre- 5.3.7
66 STORED_ENUM_MAP(stored_privileges_0, header::NoPrivileges,
67 	header::NoPrivileges,
68 	header::PowerUserPrivileges,
69 	header::AdminPriviliges,
70 );
71 
72 // post- 5.3.7
73 STORED_ENUM_MAP(stored_privileges_1, header::NoPrivileges,
74 	header::NoPrivileges,
75 	header::PowerUserPrivileges,
76 	header::AdminPriviliges,
77 	header::LowestPrivileges
78 );
79 
80 STORED_ENUM_MAP(stored_bool_yes_no_auto, header::Yes,
81 	header::Yes,
82 	header::No,
83 	header::Auto
84 );
85 
86 STORED_ENUM_MAP(stored_language_detection_method, header::UILanguage,
87 	header::UILanguage,
88 	header::LocaleLanguage,
89 	header::NoLanguageDetection
90 );
91 
92 STORED_FLAGS_MAP(stored_architectures_0,
93 	header::ArchitectureUnknown,
94 	header::X86,
95 	header::Amd64,
96 	header::IA64
97 );
98 
99 STORED_FLAGS_MAP(stored_architectures_1,
100 	header::ArchitectureUnknown,
101 	header::X86,
102 	header::Amd64,
103 	header::IA64,
104 	header::ARM64,
105 );
106 
107 // pre-4.2.5
108 STORED_ENUM_MAP(stored_compression_method_0, stream::UnknownCompression,
109 	stream::Zlib,
110 	stream::BZip2,
111 	stream::LZMA1
112 );
113 
114 // 4.2.5
115 STORED_ENUM_MAP(stored_compression_method_1, stream::UnknownCompression,
116 	stream::Stored,
117 	stream::BZip2,
118 	stream::LZMA1
119 );
120 
121 // [4.2.6 5.3.9)
122 STORED_ENUM_MAP(stored_compression_method_2, stream::UnknownCompression,
123 	stream::Stored,
124 	stream::Zlib,
125 	stream::BZip2,
126 	stream::LZMA1
127 );
128 
129 // 5.3.9+
130 STORED_ENUM_MAP(stored_compression_method_3, stream::UnknownCompression,
131 	stream::Stored,
132 	stream::Zlib,
133 	stream::BZip2,
134 	stream::LZMA1,
135 	stream::LZMA2
136 );
137 
138 // 6.0.0+
139 STORED_FLAGS_MAP(stored_privileges_required_overrides,
140 	header::Commandline,
141 	header::Dialog
142 );
143 
144 } // anonymous namespace
145 
load(std::istream & is,const version & version)146 void header::load(std::istream & is, const version & version) {
147 
148 	options = 0;
149 
150 	if(version < INNO_VERSION(1, 3, 0)) {
151 		(void)util::load<boost::uint32_t>(is); // uncompressed size of the setup header
152 	}
153 
154 	is >> util::binary_string(app_name);
155 	is >> util::binary_string(app_versioned_name);
156 	if(version >= INNO_VERSION(1, 3, 0)) {
157 		is >> util::binary_string(app_id);
158 	} else {
159 		app_id.clear();
160 	}
161 	is >> util::binary_string(app_copyright);
162 	if(version >= INNO_VERSION(1, 3, 0)) {
163 		is >> util::binary_string(app_publisher);
164 		is >> util::binary_string(app_publisher_url);
165 	} else {
166 		app_publisher.clear(), app_publisher_url.clear();
167 	}
168 	if(version >= INNO_VERSION(5, 1, 13)) {
169 		is >> util::binary_string(app_support_phone);
170 	} else {
171 		app_support_phone.clear();
172 	}
173 	if(version >= INNO_VERSION(1, 3, 0)) {
174 		is >> util::binary_string(app_support_url);
175 		is >> util::binary_string(app_updates_url);
176 		is >> util::binary_string(app_version);
177 	} else {
178 		app_support_url.clear(), app_updates_url.clear(), app_version.clear();
179 	}
180 	is >> util::binary_string(default_dir_name);
181 	is >> util::binary_string(default_group_name);
182 	if(version < INNO_VERSION(3, 0, 0)) {
183 		is >> util::ansi_string(uninstall_icon_name);
184 	} else {
185 		uninstall_icon_name.clear();
186 	}
187 	is >> util::binary_string(base_filename);
188 	if(version >= INNO_VERSION(1, 3, 0) && version < INNO_VERSION(5, 2, 5)) {
189 		is >> util::ansi_string(license_text);
190 		is >> util::ansi_string(info_before);
191 		is >> util::ansi_string(info_after);
192 	} else {
193 		license_text.clear(), info_before.clear(), info_after.clear();
194 	}
195 	if(version >= INNO_VERSION(1, 3, 3)) {
196 		is >> util::binary_string(uninstall_files_dir);
197 	} else {
198 		uninstall_files_dir.clear();
199 	}
200 	if(version >= INNO_VERSION(1, 3, 6)) {
201 		is >> util::binary_string(uninstall_name);
202 		is >> util::binary_string(uninstall_icon);
203 	} else {
204 		uninstall_name.clear(), uninstall_icon.clear();
205 	}
206 	if(version >= INNO_VERSION(1, 3, 14)) {
207 		is >> util::binary_string(app_mutex);
208 	} else {
209 		app_mutex.clear();
210 	}
211 	if(version >= INNO_VERSION(3, 0, 0)) {
212 		is >> util::binary_string(default_user_name);
213 		is >> util::binary_string(default_user_organisation);
214 	} else {
215 		default_user_name.clear(), default_user_organisation.clear();
216 	}
217 	if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION_EXT(3, 0, 6, 1))) {
218 		is >> util::binary_string(default_serial);
219 	} else {
220 		default_serial.clear();
221 	}
222 	if((version >= INNO_VERSION(4, 0, 0) && version < INNO_VERSION(5, 2, 5)) ||
223 	   (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) {
224 		is >> util::binary_string(compiled_code);
225 	} else {
226 		compiled_code.clear();
227 	}
228 	if(version >= INNO_VERSION(4, 2, 4)) {
229 		is >> util::binary_string(app_readme_file);
230 		is >> util::binary_string(app_contact);
231 		is >> util::binary_string(app_comments);
232 		is >> util::binary_string(app_modify_path);
233 	} else {
234 		app_readme_file.clear(), app_contact.clear();
235 		app_comments.clear(), app_modify_path.clear();
236 	}
237 	if(version >= INNO_VERSION(5, 3, 8)) {
238 		is >> util::binary_string(create_uninstall_registry_key);
239 	} else {
240 		create_uninstall_registry_key.clear();
241 	}
242 	if(version >= INNO_VERSION(5, 3, 10)) {
243 		is >> util::binary_string(uninstallable);
244 	} else {
245 		uninstallable.clear();
246 	}
247 	if(version >= INNO_VERSION(5, 5, 0)) {
248 		is >> util::binary_string(close_applications_filter);
249 	} else {
250 		close_applications_filter.clear();
251 	}
252 	if(version >= INNO_VERSION(5, 5, 6)) {
253 		is >> util::binary_string(setup_mutex);
254 	} else {
255 		setup_mutex.clear();
256 	}
257 	if(version >= INNO_VERSION(5, 6, 1)) {
258 		is >> util::binary_string(changes_environment);
259 		is >> util::binary_string(changes_associations);
260 	} else {
261 		changes_environment.clear();
262 		changes_associations.clear();
263 	}
264 	if(version >= INNO_VERSION(5, 2, 5)) {
265 		is >> util::ansi_string(license_text);
266 		is >> util::ansi_string(info_before);
267 		is >> util::ansi_string(info_after);
268 	}
269 	if(version >= INNO_VERSION(5, 2, 1) && version < INNO_VERSION(5, 3, 10)) {
270 		is >> util::binary_string(uninstaller_signature);
271 	} else {
272 		uninstaller_signature.clear();
273 	}
274 	if(version >= INNO_VERSION(5, 2, 5)) {
275 		is >> util::binary_string(compiled_code);
276 	}
277 
278 	if(version >= INNO_VERSION(2, 0, 6) && !version.is_unicode()) {
279 		lead_bytes = stored_char_set(is);
280 	} else {
281 		lead_bytes = 0;
282 	}
283 
284 	if(version >= INNO_VERSION(4, 0, 0)) {
285 		language_count = util::load<boost::uint32_t>(is);
286 	} else if(version >= INNO_VERSION(2, 0, 1)) {
287 		language_count = 1;
288 	} else {
289 		language_count = 0;
290 	}
291 
292 	if(version >= INNO_VERSION(4, 2, 1)) {
293 		message_count = util::load<boost::uint32_t>(is);
294 	} else {
295 		message_count = 0;
296 	}
297 
298 	if(version >= INNO_VERSION(4, 1, 0)) {
299 		permission_count = util::load<boost::uint32_t>(is);
300 	} else {
301 		permission_count = 0;
302 	}
303 
304 	if(version >= INNO_VERSION(2, 0, 0) || version.is_isx()) {
305 		type_count = util::load<boost::uint32_t>(is);
306 		component_count = util::load<boost::uint32_t>(is);
307 	} else {
308 		type_count = 0, component_count = 0;
309 	}
310 	if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 17))) {
311 		task_count = util::load<boost::uint32_t>(is);
312 	} else {
313 		task_count = 0;
314 	}
315 
316 	directory_count = util::load<boost::uint32_t>(is, version.bits());
317 	file_count = util::load<boost::uint32_t>(is, version.bits());
318 	data_entry_count = util::load<boost::uint32_t>(is, version.bits());
319 	icon_count = util::load<boost::uint32_t>(is, version.bits());
320 	ini_entry_count = util::load<boost::uint32_t>(is, version.bits());
321 	registry_entry_count = util::load<boost::uint32_t>(is, version.bits());
322 	delete_entry_count = util::load<boost::uint32_t>(is, version.bits());
323 	uninstall_delete_entry_count = util::load<boost::uint32_t>(is, version.bits());
324 	run_entry_count = util::load<boost::uint32_t>(is, version.bits());
325 	uninstall_run_entry_count = util::load<boost::uint32_t>(is, version.bits());
326 
327 	boost::int32_t license_size = 0;
328 	boost::int32_t info_before_size = 0;
329 	boost::int32_t info_after_size = 0;
330 	if(version < INNO_VERSION(1, 3, 0)) {
331 		license_size = util::load<boost::int32_t>(is, version.bits());
332 		info_before_size = util::load<boost::int32_t>(is, version.bits());
333 		info_after_size = util::load<boost::int32_t>(is, version.bits());
334 	}
335 
336 	winver.load(is, version);
337 
338 	back_color = util::load<boost::uint32_t>(is);
339 	if(version >= INNO_VERSION(1, 3, 3)) {
340 		back_color2 = util::load<boost::uint32_t>(is);
341 	} else {
342 		back_color2 = 0;
343 	}
344 	if(version < INNO_VERSION(5, 5, 7)) {
345 		image_back_color = util::load<boost::uint32_t>(is);
346 	} else {
347 		image_back_color = 0;
348 	}
349 	if((version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 4)) || version.is_isx()) {
350 		small_image_back_color = util::load<boost::uint32_t>(is);
351 	} else {
352 		small_image_back_color = 0;
353 	}
354 
355 	if(version >= INNO_VERSION(6, 0, 0)) {
356 		wizard_style = stored_enum<stored_setup_style>(is).get();
357 		wizard_resize_percent_x = util::load<boost::uint32_t>(is);
358 		wizard_resize_percent_y = util::load<boost::uint32_t>(is);
359 	} else {
360 		wizard_style = ClassicStyle;
361 		wizard_resize_percent_x = 0;
362 		wizard_resize_percent_y = 0;
363 	}
364 
365 	if(version >= INNO_VERSION(5, 5, 7)) {
366 		image_alpha_format = stored_enum<stored_alpha_format>(is).get();
367 	} else {
368 		image_alpha_format = AlphaIgnored;
369 	}
370 
371 	if(version < INNO_VERSION(4, 2, 0)) {
372 		password.crc32 = util::load<boost::uint32_t>(is);
373 		password.type = crypto::CRC32;
374 	} else if(version < INNO_VERSION(5, 3, 9)) {
375 		is.read(password.md5, std::streamsize(sizeof(password.md5)));
376 		password.type = crypto::MD5;
377 	} else {
378 		is.read(password.sha1, std::streamsize(sizeof(password.sha1)));
379 		password.type = crypto::SHA1;
380 	}
381 	if(version >= INNO_VERSION(4, 2, 2)) {
382 		password_salt.resize(8);
383 		is.read(&password_salt[0], std::streamsize(password_salt.length()));
384 		password_salt.insert(0, "PasswordCheckHash");
385 	} else {
386 		password_salt.clear();
387 	}
388 
389 	if(version >= INNO_VERSION(4, 0, 0)) {
390 		extra_disk_space_required = util::load<boost::int64_t>(is);
391 		slices_per_disk = util::load<boost::uint32_t>(is);
392 	} else {
393 		extra_disk_space_required = util::load<boost::int32_t>(is);
394 		slices_per_disk = 1;
395 	}
396 
397 	if((version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) ||
398 	   (version.is_isx() && version >= INNO_VERSION(1, 3, 4))) {
399 		install_mode = stored_enum<stored_install_verbosity>(is).get();
400 	} else {
401 		install_mode = NormalInstallMode;
402 	}
403 
404 	if(version >= INNO_VERSION(1, 3, 0)) {
405 		uninstall_log_mode = stored_enum<stored_log_mode>(is).get();
406 	} else {
407 		uninstall_log_mode = NewLog;
408 	}
409 
410 	if(version >= INNO_VERSION(5, 0, 0)) {
411 		uninstall_style = ModernStyle;
412 	} else if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 13))) {
413 		uninstall_style = stored_enum<stored_setup_style>(is).get();
414 	} else {
415 		uninstall_style = ClassicStyle;
416 	}
417 
418 	if(version >= INNO_VERSION(1, 3, 6)) {
419 		dir_exists_warning = stored_enum<stored_bool_auto_no_yes>(is).get();
420 	} else {
421 		dir_exists_warning = Auto;
422 	}
423 
424 	if(version.is_isx() && version >= INNO_VERSION(2, 0, 10) && version < INNO_VERSION(3, 0, 0)) {
425 		boost::int32_t code_line_offset = util::load<boost::int32_t>(is);
426 		(void)code_line_offset;
427 	}
428 
429 	if(version >= INNO_VERSION(3, 0, 0) && version < INNO_VERSION(3, 0, 3)) {
430 		auto_bool val = stored_enum<stored_bool_auto_no_yes>(is).get();
431 		switch(val) {
432 			case Yes: options |= AlwaysRestart; break;
433 			case Auto: options |= RestartIfNeededByRun; break;
434 			case No: break;
435 		}
436 	}
437 
438 	if(version >= INNO_VERSION(5, 3, 7)) {
439 		privileges_required = stored_enum<stored_privileges_1>(is).get();
440 	} else if(version >= INNO_VERSION(3, 0, 4) || (version.is_isx() && version >= INNO_VERSION(3, 0, 3))) {
441 		privileges_required = stored_enum<stored_privileges_0>(is).get();
442 	}
443 
444 	if(version >= INNO_VERSION(5, 7, 0)) {
445 		privileges_required_override_allowed = stored_flags<stored_privileges_required_overrides>(is).get();
446 	} else {
447 		privileges_required_override_allowed = 0;
448 	}
449 
450 	if(version >= INNO_VERSION(4, 0, 10)) {
451 		show_language_dialog = stored_enum<stored_bool_yes_no_auto>(is).get();
452 		language_detection = stored_enum<stored_language_detection_method>(is).get();
453 	}
454 
455 	if(version >= INNO_VERSION(5, 3, 9)) {
456 		compression = stored_enum<stored_compression_method_3>(is).get();
457 	} else if(version >= INNO_VERSION(4, 2, 6)) {
458 		compression = stored_enum<stored_compression_method_2>(is).get();
459 	} else if(version >= INNO_VERSION(4, 2, 5)) {
460 		compression = stored_enum<stored_compression_method_1>(is).get();
461 	} else if(version >= INNO_VERSION(4, 1, 5)) {
462 		compression = stored_enum<stored_compression_method_0>(is).get();
463 	}
464 
465 	if(version >= INNO_VERSION(5, 6, 0)) {
466 		architectures_allowed = stored_flags<stored_architectures_1>(is).get();
467 		architectures_installed_in_64bit_mode = stored_flags<stored_architectures_1>(is).get();
468 	} else if(version >= INNO_VERSION(5, 1, 0)) {
469 		architectures_allowed = stored_flags<stored_architectures_0>(is).get();
470 		architectures_installed_in_64bit_mode = stored_flags<stored_architectures_0>(is).get();
471 	} else {
472 		architectures_allowed = architecture_types::all();
473 		architectures_installed_in_64bit_mode = architecture_types::all();
474 	}
475 
476 	if(version >= INNO_VERSION(5, 2, 1) && version < INNO_VERSION(5, 3, 10)) {
477 		signed_uninstaller_original_size = util::load<boost::uint32_t>(is);
478 		signed_uninstaller_header_checksum = util::load<boost::uint32_t>(is);
479 	} else {
480 		signed_uninstaller_original_size = signed_uninstaller_header_checksum = 0;
481 	}
482 
483 	if(version >= INNO_VERSION(5, 3, 3)) {
484 		disable_dir_page = stored_enum<stored_bool_auto_no_yes>(is).get();
485 		disable_program_group_page = stored_enum<stored_bool_auto_no_yes>(is).get();
486 	}
487 
488 	if(version >= INNO_VERSION(5, 5, 0)) {
489 		uninstall_display_size = util::load<boost::uint64_t>(is);
490 	} else if(version >= INNO_VERSION(5, 3, 6)) {
491 		uninstall_display_size = util::load<boost::uint32_t>(is);
492 	} else {
493 		uninstall_display_size = 0;
494 	}
495 
496 	if(version == INNO_VERSION_EXT(5, 4,  2, 1) || version == INNO_VERSION_EXT(5, 5, 0, 1)) {
497 		/*
498 		 * This is needed to extract an Inno Setup variant (BlackBox v2?) that uses
499 		 * the 5.4.2 or 5.5.0 (unicode) data version string while the format differs:
500 		 * The language entries are off by one byte and the EncryptionUsed flag
501 		 * gets set while there is no decrypt_dll.
502 		 * I'm not sure where exactly this byte goes, but it's after the compression
503 		 * type and before EncryptionUsed flag.
504 		 * The other values/flags between here and there look sane (mostly default).
505 		 */
506 		(void)util::load<boost::uint8_t>(is);
507 	}
508 
509 	stored_flag_reader<flags> flagreader(is, version.bits());
510 
511 	flagreader.add(DisableStartupPrompt);
512 	if(version < INNO_VERSION(5, 3, 10)) {
513 		flagreader.add(Uninstallable);
514 	}
515 	flagreader.add(CreateAppDir);
516 	if(version < INNO_VERSION(5, 3, 3)) {
517 		flagreader.add(DisableDirPage);
518 	}
519 	if(version < INNO_VERSION(1, 3, 6)) {
520 		flagreader.add(DisableDirExistsWarning);
521 	}
522 	if(version < INNO_VERSION(5, 3, 3)) {
523 		flagreader.add(DisableProgramGroupPage);
524 	}
525 	flagreader.add(AllowNoIcons);
526 	if(version < INNO_VERSION(3, 0, 0) || version >= INNO_VERSION(3, 0, 3)) {
527 		flagreader.add(AlwaysRestart);
528 	}
529 	if(version < INNO_VERSION(1, 3, 3)) {
530 		flagreader.add(BackSolid);
531 	}
532 	flagreader.add(AlwaysUsePersonalGroup);
533 	flagreader.add(WindowVisible);
534 	flagreader.add(WindowShowCaption);
535 	flagreader.add(WindowResizable);
536 	flagreader.add(WindowStartMaximized);
537 	flagreader.add(EnableDirDoesntExistWarning);
538 	if(version < INNO_VERSION(4, 1, 2)) {
539 		flagreader.add(DisableAppendDir);
540 	}
541 	flagreader.add(Password);
542 	if(version >= INNO_VERSION(1, 2, 6)) {
543 		flagreader.add(AllowRootDirectory);
544 	}
545 	if(version >= INNO_VERSION(1, 2, 14)) {
546 		flagreader.add(DisableFinishedPage);
547 	}
548 	if(version.bits() != 16) {
549 		if(version < INNO_VERSION(3, 0, 4)) {
550 			flagreader.add(AdminPrivilegesRequired);
551 		}
552 		if(version < INNO_VERSION(3, 0, 0)) {
553 			flagreader.add(AlwaysCreateUninstallIcon);
554 		}
555 		if(version < INNO_VERSION(1, 3, 6)) {
556 			flagreader.add(OverwriteUninstRegEntries);
557 		}
558 		if(version < INNO_VERSION(5, 6, 1)) {
559 			flagreader.add(ChangesAssociations);
560 		}
561 	}
562 	if(version >= INNO_VERSION(1, 3, 0) && version < INNO_VERSION(5, 3, 8)) {
563 		flagreader.add(CreateUninstallRegKey);
564 	}
565 	if(version >= INNO_VERSION(1, 3, 1)) {
566 		flagreader.add(UsePreviousAppDir);
567 	}
568 	if(version >= INNO_VERSION(1, 3, 3)) {
569 		flagreader.add(BackColorHorizontal);
570 	}
571 	if(version >= INNO_VERSION(1, 3, 10)) {
572 		flagreader.add(UsePreviousGroup);
573 	}
574 	if(version >= INNO_VERSION(1, 3, 20)) {
575 		flagreader.add(UpdateUninstallLogAppName);
576 	}
577 	if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 10))) {
578 		flagreader.add(UsePreviousSetupType);
579 	}
580 	if(version >= INNO_VERSION(2, 0, 0)) {
581 		flagreader.add(DisableReadyMemo);
582 		flagreader.add(AlwaysShowComponentsList);
583 		flagreader.add(FlatComponentsList);
584 		flagreader.add(ShowComponentSizes);
585 		flagreader.add(UsePreviousTasks);
586 		flagreader.add(DisableReadyPage);
587 	}
588 	if(version >= INNO_VERSION(2, 0, 7)) {
589 		flagreader.add(AlwaysShowDirOnReadyPage);
590 		flagreader.add(AlwaysShowGroupOnReadyPage);
591 	}
592 	if(version >= INNO_VERSION(2, 0, 17) && version < INNO_VERSION(4, 1, 5)) {
593 		flagreader.add(BzipUsed);
594 	}
595 	if(version >= INNO_VERSION(2, 0, 18)) {
596 		flagreader.add(AllowUNCPath);
597 	}
598 	if(version >= INNO_VERSION(3, 0, 0)) {
599 		flagreader.add(UserInfoPage);
600 		flagreader.add(UsePreviousUserInfo);
601 	}
602 	if(version >= INNO_VERSION(3, 0, 1)) {
603 		flagreader.add(UninstallRestartComputer);
604 	}
605 	if(version >= INNO_VERSION(3, 0, 3)) {
606 		flagreader.add(RestartIfNeededByRun);
607 	}
608 	if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(3, 0, 3))) {
609 		flagreader.add(ShowTasksTreeLines);
610 	}
611 	if(version >= INNO_VERSION(4, 0, 0) && version < INNO_VERSION(4, 0, 10)) {
612 		flagreader.add(ShowLanguageDialog);
613 	}
614 	if(version >= INNO_VERSION(4, 0, 1) && version < INNO_VERSION(4, 0, 10)) {
615 		flagreader.add(DetectLanguageUsingLocale);
616 	}
617 	if(version >= INNO_VERSION(4, 0, 9)) {
618 		flagreader.add(AllowCancelDuringInstall);
619 	} else {
620 		options |= AllowCancelDuringInstall;
621 	}
622 	if(version >= INNO_VERSION(4, 1, 3)) {
623 		flagreader.add(WizardImageStretch);
624 	}
625 	if(version >= INNO_VERSION(4, 1, 8)) {
626 		flagreader.add(AppendDefaultDirName);
627 		flagreader.add(AppendDefaultGroupName);
628 	}
629 	if(version >= INNO_VERSION(4, 2, 2)) {
630 		flagreader.add(EncryptionUsed);
631 	}
632 	if(version >= INNO_VERSION(5, 0, 4) && version < INNO_VERSION(5, 6, 1)) {
633 		flagreader.add(ChangesEnvironment);
634 	}
635 	if(version >= INNO_VERSION(5, 1, 7) && !version.is_unicode()) {
636 		flagreader.add(ShowUndisplayableLanguages);
637 	}
638 	if(version >= INNO_VERSION(5, 1, 13)) {
639 		flagreader.add(SetupLogging);
640 	}
641 	if(version >= INNO_VERSION(5, 2, 1)) {
642 		flagreader.add(SignedUninstaller);
643 	}
644 	if(version >= INNO_VERSION(5, 3, 8)) {
645 		flagreader.add(UsePreviousLanguage);
646 	}
647 	if(version >= INNO_VERSION(5, 3, 9)) {
648 		flagreader.add(DisableWelcomePage);
649 	}
650 	if(version >= INNO_VERSION(5, 5, 0)) {
651 		flagreader.add(CloseApplications);
652 		flagreader.add(RestartApplications);
653 		flagreader.add(AllowNetworkDrive);
654 	} else {
655 		options |= AllowNetworkDrive;
656 	}
657 	if(version >= INNO_VERSION(5, 5, 7)) {
658 		flagreader.add(ForceCloseApplications);
659 	}
660 	if(version >= INNO_VERSION(6, 0, 0)) {
661 		flagreader.add(AppNameHasConsts);
662 		flagreader.add(UsePreviousPrivileges);
663 		flagreader.add(WizardResizable);
664 	}
665 
666 	options |= flagreader;
667 
668 	if(version < INNO_VERSION(3, 0, 4)) {
669 		privileges_required = (options & AdminPrivilegesRequired) ? AdminPriviliges : NoPrivileges;
670 	}
671 
672 	if(version < INNO_VERSION(4, 0, 10)) {
673 		show_language_dialog = (options & ShowLanguageDialog) ? Yes : No;
674 		language_detection = (options & DetectLanguageUsingLocale) ? LocaleLanguage : UILanguage;
675 	}
676 
677 	if(version < INNO_VERSION(4, 1, 5)) {
678 		compression = (options & BzipUsed) ? stream::BZip2 : stream::Zlib;
679 	}
680 
681 	if(version < INNO_VERSION(5, 3, 3)) {
682 		disable_dir_page = (options & DisableDirPage) ? Yes : No;
683 		disable_program_group_page = (options & DisableProgramGroupPage) ? Yes : No;
684 	}
685 
686 	if(version < INNO_VERSION(1, 3, 0)) {
687 		if(license_size > 0) {
688 			license_text.resize(size_t(license_size));
689 			is.read(&license_text[0], license_size);
690 			util::to_utf8(license_text);
691 		}
692 		if(info_before_size > 0) {
693 			info_before.resize(size_t(info_before_size));
694 			is.read(&info_before[0], info_before_size);
695 			util::to_utf8(info_before);
696 		}
697 		if(info_after_size > 0) {
698 			info_after.resize(size_t(info_after_size));
699 			is.read(&info_after[0], info_after_size);
700 			util::to_utf8(info_after);
701 		}
702 	}
703 
704 }
705 
decode(util::codepage_id codepage)706 void header::decode(util::codepage_id codepage) {
707 
708 	util::to_utf8(app_name, codepage);
709 	util::to_utf8(app_versioned_name, codepage);
710 	util::to_utf8(app_id, codepage);
711 	util::to_utf8(app_copyright, codepage);
712 	util::to_utf8(app_publisher, codepage);
713 	util::to_utf8(app_publisher_url, codepage);
714 	util::to_utf8(app_support_phone, codepage);
715 	util::to_utf8(app_support_url, codepage);
716 	util::to_utf8(app_updates_url, codepage);
717 	util::to_utf8(app_version, codepage);
718 	util::to_utf8(default_dir_name, codepage, &lead_bytes);
719 	util::to_utf8(default_group_name, codepage);
720 	util::to_utf8(base_filename, codepage, &lead_bytes);
721 	util::to_utf8(uninstall_files_dir, codepage, &lead_bytes);
722 	util::to_utf8(uninstall_name, codepage, &lead_bytes);
723 	util::to_utf8(uninstall_icon, codepage, &lead_bytes);
724 	util::to_utf8(app_mutex, codepage, &lead_bytes);
725 	util::to_utf8(default_user_name, codepage);
726 	util::to_utf8(default_user_organisation, codepage);
727 	util::to_utf8(default_serial, codepage);
728 	util::to_utf8(app_readme_file, codepage, &lead_bytes);
729 	util::to_utf8(app_contact, codepage);
730 	util::to_utf8(app_comments, codepage);
731 	util::to_utf8(app_modify_path, codepage, &lead_bytes);
732 	util::to_utf8(create_uninstall_registry_key, codepage, &lead_bytes);
733 	util::to_utf8(uninstallable, codepage);
734 	util::to_utf8(close_applications_filter, codepage);
735 	util::to_utf8(setup_mutex, codepage, &lead_bytes);
736 	util::to_utf8(changes_environment, codepage);
737 	util::to_utf8(changes_associations, codepage);
738 
739 }
740 
741 } // namespace setup
742 
743 NAMES(setup::header::flags, "Setup Option",
744 	"disable startup prompt",
745 	"create app dir",
746 	"allow no icons",
747 	"always restart",
748 	"always use personal group",
749 	"window visible",
750 	"window show caption",
751 	"window resizable",
752 	"window start maximized",
753 	"enable dir doesn't exist warning",
754 	"password",
755 	"allow root directory",
756 	"disable finished page",
757 	"changes associations",
758 	"use previous app dir",
759 	"back color horizontal",
760 	"use previous group",
761 	"update uninstall log app name",
762 	"use previous setup type",
763 	"disable ready memo",
764 	"always show components list",
765 	"flat components list",
766 	"show component sizes",
767 	"use previous tasks",
768 	"disable ready page",
769 	"always show dir on ready page",
770 	"always show group on ready page",
771 	"allow unc path",
772 	"user info page",
773 	"use previous user info",
774 	"uninstall restart computer",
775 	"restart if needed by run",
776 	"show tasks tree lines",
777 	"allow cancel during install",
778 	"wizard image stretch",
779 	"append default dir name",
780 	"append default group name",
781 	"encrypted",
782 	"changes environment",
783 	"show undisplayable languages",
784 	"setup logging",
785 	"signed uninstaller",
786 	"use previous language",
787 	"disable welcome page",
788 	"close applications",
789 	"restart applications",
790 	"allow network drive",
791 	"force close applications",
792 	"uninstallable",
793 	"disable dir page",
794 	"disable program group page",
795 	"disable append dir",
796 	"admin privilegesrequired",
797 	"always create uninstall icon",
798 	"create uninstall reg key",
799 	"bzip used",
800 	"show language dialog",
801 	"detect language using locale",
802 	"disable dir exists warning",
803 	"back solid",
804 	"overwrite uninst reg entries",
805 )
806 
807 NAMES(setup::header::architecture_types, "Architecture",
808 	"unknown",
809 	"x86",
810 	"amd64",
811 	"IA64",
812 	"ARM64",
813 )
814 
815 NAMES(setup::header::privileges_required_overrides, "Priviledge Override"
816 	"commandline",
817 	"dialog",
818 )
819 
820 NAMES(setup::header::alpha_format, "Alpha Format",
821 	"ignored",
822 	"defined",
823 	"premultiplied",
824 )
825 
826 NAMES(setup::header::install_verbosity, "Install Mode",
827 	"normal",
828 	"silent",
829 	"very silent",
830 )
831 
832 NAMES(setup::header::log_mode, "Uninstall Log Mode",
833 	"append",
834 	"new log",
835 	"overwrite",
836 )
837 
838 NAMES(setup::header::style, "Style",
839 	"classic",
840 	"modern",
841 )
842 
843 NAMES(setup::header::auto_bool, "Auto Boolean",
844 	"auto",
845 	"no",
846 	"yes",
847 )
848 
849 NAMES(setup::header::privilege_level, "Privileges",
850 	"none",
851 	"power user",
852 	"admin",
853 	"lowest",
854 )
855 
856 NAMES(setup::header::language_detection_method, "Language Detection",
857 	"ui language",
858 	"locale",
859 	"none",
860 )
861