From f0e12bc695641d684ea9ca0809572c339aed536b Mon Sep 17 00:00:00 2001 From: Daniel Scharrer Date: Tue, 27 Sep 2011 20:42:38 +0200 Subject: [PATCH] Implement reading language entries. --- CMakeLists.txt | 1 + src/BlockReader.cpp | 1 - src/ChunkFilter.hpp | 2 +- src/ExeFormat.hpp | 2 +- src/ExeReader.cpp | 2 +- src/ExeReader.hpp | 5 + src/InnoExtract.cpp | 36 +- src/LanguageEntry.cpp | 60 +++ src/LanguageEntry.hpp | 35 ++ src/LoadingUtils.cpp | 6 +- src/LoadingUtils.hpp | 2 +- src/LzmaFilter.cpp | 2 +- src/LzmaFilter.hpp | 13 + src/SetupHeader.cpp | 2 +- src/SetupHeader.hpp | 2 +- src/SetupHeaderFormat.hpp | 638 +-------------------------- src/SetupLoader.hpp | 7 +- src/SetupLoaderFormat.hpp | 2 +- src/StoredEnum.hpp | 196 ++++++++ src/{Types.h => Types.hpp} | 5 + src/Version.hpp | 2 +- src/{ => misc}/BitfieldConverter.hpp | 0 src/{ => misc}/UnDeflate.cpp | 0 test.cpp => src/misc/test.cpp | 0 24 files changed, 370 insertions(+), 651 deletions(-) create mode 100644 src/LanguageEntry.cpp create mode 100644 src/LanguageEntry.hpp create mode 100644 src/StoredEnum.hpp rename src/{Types.h => Types.hpp} (73%) rename src/{ => misc}/BitfieldConverter.hpp (100%) rename src/{ => misc}/UnDeflate.cpp (100%) rename test.cpp => src/misc/test.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 897a877..a54144a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ set(INNOEXTRACT_SOURCES src/ChunkFilter.cpp src/ExeReader.cpp src/InnoExtract.cpp + src/LanguageEntry.cpp src/LoadingUtils.cpp src/LzmaFilter.cpp src/Output.cpp diff --git a/src/BlockReader.cpp b/src/BlockReader.cpp index 2f53558..1c26e50 100644 --- a/src/BlockReader.cpp +++ b/src/BlockReader.cpp @@ -8,7 +8,6 @@ #include #include -#include "Types.h" #include "Utils.hpp" #include "ChunkFilter.hpp" #include "LzmaFilter.hpp" diff --git a/src/ChunkFilter.hpp b/src/ChunkFilter.hpp index afda40d..ce884fd 100644 --- a/src/ChunkFilter.hpp +++ b/src/ChunkFilter.hpp @@ -9,7 +9,7 @@ #include #include -#include "Types.h" +#include "Types.hpp" #include "Output.hpp" class inno_chunk_filter : public boost::iostreams::multichar_input_filter { diff --git a/src/ExeFormat.hpp b/src/ExeFormat.hpp index bb8d8e5..88679cb 100644 --- a/src/ExeFormat.hpp +++ b/src/ExeFormat.hpp @@ -1,5 +1,5 @@ -#include "Types.h" +#include "Types.hpp" # pragma pack(push, 1) diff --git a/src/ExeReader.cpp b/src/ExeReader.cpp index 10c0c93..ba8d548 100644 --- a/src/ExeReader.cpp +++ b/src/ExeReader.cpp @@ -6,7 +6,7 @@ #include #include -#include "Types.h" +#include "Types.hpp" #include "ExeFormat.hpp" #include "Utils.hpp" #include "Output.hpp" diff --git a/src/ExeReader.hpp b/src/ExeReader.hpp index 5651e39..9111988 100644 --- a/src/ExeReader.hpp +++ b/src/ExeReader.hpp @@ -1,4 +1,7 @@ +#ifndef INNOEXTRACT_EXEREADER_HPP +#define INNOEXTRACT_EXEREADER_HPP + #include #include #include @@ -44,3 +47,5 @@ private: static size_t memoryAddressToFileOffset(const CoffSectionTable & sections, size_t memory); }; + +#endif // INNOEXTRACT_EXEREADER_HPP diff --git a/src/InnoExtract.cpp b/src/InnoExtract.cpp index 9460cc6..90d0e56 100644 --- a/src/InnoExtract.cpp +++ b/src/InnoExtract.cpp @@ -11,12 +11,12 @@ #include -#include "Types.h" #include "SetupHeader.hpp" #include "SetupLoader.hpp" #include "Utils.hpp" #include "Output.hpp" #include "BlockReader.hpp" +#include "LanguageEntry.hpp" using std::cout; using std::string; @@ -218,5 +218,39 @@ int main(int argc, char * argv[]) { cout << color::reset; + if(header.numLanguageEntries) { + cout << "Language entries:" << endl; + } + for(size_t i = 0; i < header.numLanguageEntries; i++) { + + LanguageEntry entry; + entry.load(is, version); + if(is.fail()) { + error << "error reading language entry #" << i; + } + + cout << " - " << Quoted(entry.name) << ':' << endl; + cout << IfNotEmpty(" Language name", entry.languageName); + cout << IfNotEmpty(" Dialog font", entry.dialogFontName); + cout << IfNotEmpty(" Title font", entry.titleFontName); + cout << IfNotEmpty(" Welcome font", entry.welcomeFontName); + cout << IfNotEmpty(" Copyright font", entry.copyrightFontName); + cout << IfNotEmpty(" Data", entry.data); + cout << IfNotEmpty(" License", entry.licenseText); + cout << IfNotEmpty(" Info before text", entry.infoBeforeText); + cout << IfNotEmpty(" Info after text", entry.infoAfterText); + + cout << " Language id: " << hex << entry.languageId << dec << endl; + + cout << IfNotZero(" Codepage", entry.languageCodePage); + cout << IfNotZero(" Dialog font size", entry.dialogFontSize); + cout << IfNotZero(" Dialog font standard height", entry.dialogFontStandardHeight); + cout << IfNotZero(" Title font size", entry.titleFontSize); + cout << IfNotZero(" Welcome font size", entry.welcomeFontSize); + cout << IfNotZero(" Copyright font size", entry.copyrightFontSize); + cout << IfNot(" Right to left", entry.rightToLeft, false); + + }; + return 0; } diff --git a/src/LanguageEntry.cpp b/src/LanguageEntry.cpp new file mode 100644 index 0000000..20e8e46 --- /dev/null +++ b/src/LanguageEntry.cpp @@ -0,0 +1,60 @@ + +#include "LanguageEntry.hpp" + +#include +#include +#include "LoadingUtils.hpp" +#include "Output.hpp" + +void convert(iconv_t converter, const std::string & from, std::string & to); + +void LanguageEntry::load(std::istream & is, const InnoVersion & version) { + + // introduced in version 4.0.0 + + is >> WideString(name, version.unicode); + + is >> WideString(languageName, version >= INNO_VERSION(4, 2, 2)); + + is >> WideString(dialogFontName, version.unicode); + is >> WideString(titleFontName, version.unicode); + is >> WideString(welcomeFontName, version.unicode); + is >> WideString(copyrightFontName, version.unicode); + + is >> BinaryString(data); + + if(version >= INNO_VERSION(4, 0, 1)) { + is >> AnsiString(licenseText); + is >> AnsiString(infoBeforeText); + is >> AnsiString(infoAfterText); + } else { + licenseText.clear(), infoBeforeText.clear(), infoAfterText.clear(); + } + + languageId = loadNumber(is); + + if(version >= INNO_VERSION(4, 2, 2) && (version < INNO_VERSION(5, 3, 0) || !version.unicode)) { + languageCodePage = loadNumber(is); + } else { + languageCodePage = 0; + } + + dialogFontSize = loadNumber(is); + + if(version < INNO_VERSION(4, 1, 0)) { + dialogFontStandardHeight = loadNumber(is); + } else { + dialogFontStandardHeight = 0; + } + + titleFontSize = loadNumber(is); + welcomeFontSize = loadNumber(is); + copyrightFontSize = loadNumber(is); + + if(version >= INNO_VERSION(5, 2, 3)) { + rightToLeft = ::load(is); + } else { + rightToLeft = false; + } + +} diff --git a/src/LanguageEntry.hpp b/src/LanguageEntry.hpp new file mode 100644 index 0000000..de45f06 --- /dev/null +++ b/src/LanguageEntry.hpp @@ -0,0 +1,35 @@ + +#ifndef INNOEXTRACT_LANGUAGEENTRY_HPP +#define INNOEXTRACT_LANGUAGEENTRY_HPP + +#include +#include "Version.hpp" + +struct LanguageEntry { + + std::string name; + std::string languageName; + std::string dialogFontName; + std::string titleFontName; + std::string welcomeFontName; + std::string copyrightFontName; + std::string data; + std::string licenseText; + std::string infoBeforeText; + std::string infoAfterText; + + u32 languageId; + u32 languageCodePage; + size_t dialogFontSize; + size_t dialogFontStandardHeight; + size_t titleFontSize; + size_t welcomeFontSize; + size_t copyrightFontSize; + + bool rightToLeft; + + void load(std::istream & is, const InnoVersion & version); + +}; + +#endif // INNOEXTRACT_LANGUAGEENTRY_HPP diff --git a/src/LoadingUtils.cpp b/src/LoadingUtils.cpp index 45c5cc6..e450741 100644 --- a/src/LoadingUtils.cpp +++ b/src/LoadingUtils.cpp @@ -20,7 +20,7 @@ void BinaryString::loadInto(std::istream & is, std::string & target) { is.read(&target[0], length); } -static void convert(iconv_t converter, const std::string & from, std::string & to) { +void convert(iconv_t converter, const std::string & from, std::string & to) { const char * inbuf = from.data(); size_t insize = from.size(); @@ -36,7 +36,7 @@ static void convert(iconv_t converter, const std::string & from, std::string & t while(insize) { - to.resize(outbase + insize); + to.resize(outbase + insize + 4); char * outbuf = &to[0] + outbase; size_t outsize = to.size() - outbase; @@ -51,6 +51,8 @@ static void convert(iconv_t converter, const std::string & from, std::string & t outbase = to.size() - outsize; } + to.resize(outbase); + } void AnsiString::loadInto(std::istream & is, std::string & target) { diff --git a/src/LoadingUtils.hpp b/src/LoadingUtils.hpp index adf2986..9b56e1b 100644 --- a/src/LoadingUtils.hpp +++ b/src/LoadingUtils.hpp @@ -6,7 +6,7 @@ #include #include #include -#include "Types.h" +#include "Types.hpp" inline u8 fromLittleEndian(u8 value) { return value; } inline s8 fromLittleEndian(s8 value) { return value; } diff --git a/src/LzmaFilter.cpp b/src/LzmaFilter.cpp index 7e1ab55..d52c4ea 100644 --- a/src/LzmaFilter.cpp +++ b/src/LzmaFilter.cpp @@ -5,7 +5,7 @@ #include -#include "Types.h" +#include "Types.hpp" using std::cout; using std::endl; diff --git a/src/LzmaFilter.hpp b/src/LzmaFilter.hpp index 32e2224..7483948 100644 --- a/src/LzmaFilter.hpp +++ b/src/LzmaFilter.hpp @@ -1,4 +1,7 @@ +#ifndef INNOEXTRACT_LZMAFILTER_HPP +#define INNOEXTRACT_LZMAFILTER_HPP + #include class lzma_error { @@ -37,6 +40,14 @@ private: }; +/*! + * A filter that decompressess LZMA1 streams found in Inno Setup installers, + * to be used with boost::iostreams. + * + * The LZMA1 streams used by Inno Setup differ slightly from the LZMA Alone file format: + * The stream header only stores the properties (lc, lp, pb) and the dictionary size and + * is missing the uncompressed size field. The fiels that are present are encoded identically. + */ template > struct basic_inno_lzma_decompressor : public boost::iostreams::symmetric_filter { @@ -63,3 +74,5 @@ typedef basic_inno_lzma_decompressor<> inno_lzma_decompressor; template basic_inno_lzma_decompressor::basic_inno_lzma_decompressor(int buffer_size) : base_type(buffer_size) { } + +#endif // INNOEXTRACT_LZMAFILTER_HPP diff --git a/src/SetupHeader.cpp b/src/SetupHeader.cpp index 1bbf306..d2e431b 100644 --- a/src/SetupHeader.cpp +++ b/src/SetupHeader.cpp @@ -32,7 +32,7 @@ void SetupHeader::load(std::istream & is, const InnoVersion & version) { options = 0; if(version <= INNO_VERSION(1, 2, 16)) { - loadNumber(is); // uncompressed size of the setup header structure + ::load(is); // uncompressed size of the setup header structure } is >> WideString(appName, version.unicode); diff --git a/src/SetupHeader.hpp b/src/SetupHeader.hpp index 81ac140..304155c 100644 --- a/src/SetupHeader.hpp +++ b/src/SetupHeader.hpp @@ -6,7 +6,7 @@ #include #include #include -#include "Types.h" +#include "Types.hpp" #include "Flags.hpp" #include "Enum.hpp" #include "Version.hpp" diff --git a/src/SetupHeaderFormat.hpp b/src/SetupHeaderFormat.hpp index 18ce8dc..431d6bc 100644 --- a/src/SetupHeaderFormat.hpp +++ b/src/SetupHeaderFormat.hpp @@ -1,314 +1,6 @@ -#include -#include -#include - -#include "Types.h" #include "SetupHeader.hpp" -#include "LoadingUtils.hpp" -#include "Enum.hpp" -#include "Output.hpp" - -template -struct EnumValueMap { - - typedef Enum enum_type; - typedef Enum flag_type; - -}; - -#define STORED_ENUM_MAP(MapName, Default, ...) \ -struct MapName : public EnumValueMap { \ - static const flag_type default_value; \ - static const flag_type values[]; \ - static const size_t count; \ -}; \ -const MapName::flag_type MapName::default_value = Default; \ -const MapName::flag_type MapName::values[] = { __VA_ARGS__ }; \ -const size_t MapName::count = ARRAY_SIZE(MapName::values) - -#define STORED_FLAGS_MAP(MapName, Flag0, ...) STORED_ENUM_MAP(MapName, Flag0, Flag0, ## __VA_ARGS__) - -template -struct StoredEnum { - - u32 value; - -public: - - typedef Mapping mapping_type; - typedef typename Mapping::enum_type enum_type; - - static const size_t size = Mapping::count; - - inline StoredEnum(std::istream & is) { - value = loadNumber(is); // TODO use larger types for larger enums - } - - enum_type get() { - - if(value < size) { - return Mapping::values[value]; - } - - warning << "warning: unexpected " << EnumNames::name << " value: " << value; - - return Mapping::default_value; - } - -}; - -template -class StoredBitfield { - - typedef u8 base_type; - - static const size_t base_size = sizeof(base_type) * 8; - static const size_t count = (Bits + (base_size - 1)) / base_size; // ceildiv - - base_type bits[count]; - -public: - - static const size_t size = Bits; - - inline StoredBitfield(std::istream & is) { - for(size_t i = 0; i < count; i++) { - bits[i] = loadNumber(is); - } - } - - inline u64 getLowerBits() const { - - BOOST_STATIC_ASSERT(sizeof(u64) % sizeof(base_type) == 0); - - u64 result = 0; - - for(size_t i = 0; i < std::min(sizeof(u64) / sizeof(base_type), count); i++) { - result |= (u64(bits[i]) << (i * base_size)); - } - - return result; - } - - inline std::bitset getBitSet() const { - - static const size_t ulong_size = sizeof(unsigned long) * 8; - - BOOST_STATIC_ASSERT(base_size % ulong_size == 0 || base_size < ulong_size); - - std::bitset result(0); - for(size_t i = 0; i < count; i++) { - for(size_t j = 0; j < ceildiv(base_size, ulong_size); j++) { - result |= std::bitset(static_cast(bits[i] >> (j * ulong_size))) - << ((i * base_size) + (j * ulong_size)); - } - } - return result; - } - -}; - -template -class StoredFlags : private StoredBitfield { - -public: - - typedef Mapping mapping_type; - typedef typename Mapping::enum_type enum_type; - typedef Flags flag_type; - - inline StoredFlags(std::istream & is) : StoredBitfield(is) { } - - flag_type get() { - - u64 bits = this->getLowerBits(); - flag_type result = 0; - - for(size_t i = 0; i < this->size; i++) { - if(bits & (u64(1) << i)) { - result |= Mapping::values[i]; - bits &= ~(u64(1) << i); - } - } - - if(bits) { - warning << "unexpected " << EnumNames::name << " flags: " << std::hex << bits << std::dec; - } - - return result; - } - -}; - -template -class StoredFlagReader { - -public: - - typedef Enum enum_type; - typedef Flags flag_type; - - std::vector mappings; - - void add(enum_type flag) { - mappings.push_back(flag); - } - - - flag_type get(std::istream & is) { - - u64 bits = 0; - - /* - if(mappings.size() <= 32) { - bits = loadNumber(is); - } else if(mappings.size() <= 256) { - bits = loadNumber(is); - for(size_t i = 1; i < 4; i++) { - u64 temp = loadNumber(is); - if(temp) { - warning << "unexpected " << EnumNames::name << " flags: " << std::hex << bits << std::dec << " @ " << i; - } - } - } else { - error << "error reading " << EnumNames::name << ": too many flags: " << mappings.size(); - bits = 0; - }*/ - - typedef u8 stored_type; - static const size_t stored_bits = sizeof(stored_type) * 8; - for(size_t i = 0; i < ceildiv(mappings.size(), stored_bits); i++) { - bits |= u64(load(is)) << (i * stored_bits); - } - - std::cout << "read " << mappings.size() << " flags: " << std::hex << bits << std::dec << std::endl; - - flag_type result = 0; - - for(size_t i = 0; i < mappings.size(); i++) { - if(bits & (u64(1) << i)) { - result |= mappings[i]; - bits &= ~(u64(1) << i); - } - } - - if(bits) { - warning << "unexpected " << EnumNames::name << " flags: " << std::hex << bits << std::dec; - } - - return result; - } - -}; - -template -class StoredFlagReader > : public StoredFlagReader { }; - -/* -enum _SetupHeaderOption { - - shDisableStartupPrompt, - shUninstallable, // TODO removed in 5.3.10 - shCreateAppDir, - shDisableDirPage, // TODO removed in 5.3.3 - shDisableDirExistsWarning, // TODO only in 1.2.10, not in 1.3.25 - shDisableProgramGroupPage, // TODO removed in 5.3.3 - shAllowNoIcons, - shAlwaysRestart, // TODO missing in [3.0.0, 3.0.3) - shBackSolid, // TODO only in 1.2.10, not in 1.3.25 - shAlwaysUsePersonalGroup, - shWindowVisible, - shWindowShowCaption, - shWindowResizable, - shWindowStartMaximized, - shEnableDirDoesntExistWarning, - shDisableAppendDir, // TODO removed in 4.1.2 - shPassword, - shAllowRootDirectory, - shDisableFinishedPage, - shAdminPrivilegesRequired, // TODO removed in 3.0.4, 1.2.10: win32-only - shAlwaysCreateUninstallIcon, // TODO removed in 3.0.0, 1.2.10: win32-only - shOverwriteUninstRegEntries, // TODO only in 1.2.10, win32-only, not in 1.3.25 - shChangesAssociations, // TODO 1.2.10: win32-only - - // new after 1.2.16, in 1.3.25 - shCreateUninstallRegKey, // TODO removed in 5.3.8 - shUsePreviousAppDir, - shBackColorHorizontal, - shUsePreviousGroup, - shUpdateUninstallLogAppName, - - // new after 1.3.26 - shUsePreviousSetupType, - shDisableReadyMemo, - shAlwaysShowComponentsList, - shFlatComponentsList, - shShowComponentSizes, - shUsePreviousTasks, - shDisableReadyPage, - shAlwaysShowDirOnReadyPage, - shAlwaysShowGroupOnReadyPage, - - // only in [2.0.17, 4.1.5) - shBzipUsed, - - // new in 2.0.18 - shAllowUNCPath, - - // new in 3.0.0 - shUserInfoPage, - shUsePreviousUserInfo, - - // new in 3.0.1 - shUninstallRestartComputer, - - // new in 3.0.3 - shRestartIfNeededByRun, - - // new in 3.0.6.1 - shShowTasksTreeLines, - - // only in [4.0.0, 4.0.10) - shShowLanguageDialog, - - // only in [4.0.1, 4.0.10) - shDetectLanguageUsingLocale, - - // new in 4.0.9 - shAllowCancelDuringInstall, - - // new in 4.1.3 - shWizardImageStretch, - - // new in 4.1.8 - shAppendDefaultDirName, - shAppendDefaultGroupName, - - // new in 4.2.2 - shEncryptionUsed, - - // new in 5.0.4 - shChangesEnvironment, - - // new in 5.1.7 - shShowUndisplayableLanguages, // TODO 5.2.5+: only if not unicode - - // new in 5.1.13 - shSetupLogging, - - // new in 5.2.1 - shSignedUninstaller, - - // new in 5.3.8 - shUsePreviousLanguage, - - // new in 5.3.9 - shDisableWelcomePage, - -};*/ - -typedef StoredBitfield<256> CharSet; +#include "StoredEnum.hpp" STORED_ENUM_MAP(StoredInstallMode, SetupHeader::NormalInstallMode, SetupHeader::NormalInstallMode, @@ -409,331 +101,3 @@ STORED_ENUM_MAP(StoredDisablePage, SetupHeader::Auto, SetupHeader::No, SetupHeader::Yes ); - -/* -struct SetupHeader { - - union { - - struct { - - std::string AppName, AppVerName, AppId, AppCopyright; // String TODO 1.2.10: PChar - std::string AppPublisher, AppPublisherURL; // String TODO not in 1.2.10 - std::string AppSupportPhone; // String TODO new in 5.1.13 - std::string AppSupportURL, AppUpdatesURL, AppVersion; // String TODO not in 1.2.10 - std::string DefaultDirName, DefaultGroupName; // String - std::string UninstallIconName; // String TODO removed in 3.0.0 - std::string BaseFilename; //String - std::string LicenseText, InfoBeforeText, InfoAfterText, UninstallFilesDir, - UninstallDisplayName, UninstallDisplayIcon, AppMutex; // String TODO not in 1.2.10 - std::string DefaultUserInfoName, DefaultUserInfoOrg; // String TODO new in 3.0.0 - std::string DefaultUserInfoSerial, CompiledCodeText; // String TODO new in 3.0.6.1 - std::string AppReadmeFile, AppContact, AppComments, AppModifyPath; // String TODO new in 4.2.4 - std::string SignedUninstallerSignature; // String TODO new in 5.2.1 - - }; - - struct { // TODO 5.2.5+ - - std::wstring AppName, AppVerName, AppId, AppCopyright, AppPublisher, AppPublisherURL, - AppSupportPhone, AppSupportURL, AppUpdatesURL, AppVersion, DefaultDirName, - DefaultGroupName, BaseFilename, UninstallFilesDir, UninstallDisplayName, - UninstallDisplayIcon, AppMutex, DefaultUserInfoName, DefaultUserInfoOrg, - DefaultUserInfoSerial, AppReadmeFile, AppContact, AppComments, - AppModifyPath; // String / WideString - - std::string CreateUninstallRegKey; // String / WideString TODO new in 5.3.8 - std::string Uninstallable; // String / WideString TODO new in 5.3.10 - - std::string LicenseText, InfoBeforeText, InfoAfterText; // AnsiString - std::string SignedUninstallerSignature; // AnsiString TODO removed in 5.3.10 - std::string CompiledCodeText; // AnsiString - - }; - - }; - - CharSet LeadBytes; // set of Char TODO 5.2.5+: set of AnsiChar, only exists if not unicode - - s32 NumLanguageEntries; // Integer TODO new in 4.0.0 - s32 NumCustomMessageEntries; // Integer TODO new in 4.2.1 - s32 NumPermissionEntries; // Integer TODO new in 4.1.0 - s32 NumTypeEntries, NumComponentEntries, NumTaskEntries; // Integer TODO not in 1.2.10, not in 1.3.25 - s32 NumDirEntries, NumFileEntries, NumFileLocationEntries, NumIconEntries, - NumIniEntries, NumRegistryEntries, NumInstallDeleteEntries, - NumUninstallDeleteEntries, NumRunEntries, NumUninstallRunEntries; // Integer - - u32 LicenseSize, InfoBeforeSize, InfoAfterSize; // Cardinal TODO only in 1.2.10 - - union { - LegacySetupVersionData MinVersion, OnlyBelowVersion; // TODO only in 1.2.10 - SetupVersionData MinVersion, OnlyBelowVersion; - }; - - s32 BackColor; // LongInt - s32 BackColor2; // LongInt TODO not in 1.2.10 - s32 WizardImageBackColor; // LongInt - s32 WizardSmallImageBackColor; // LongInt TODO removed in 4.0.4, not in 1.2.10, not in 1.3.25 - union { - s32 Password; // LongInt TODO removed in 4.2.0 - MD5Digest PasswordHash; // TODO only in [4.2.0, 5.3.9) - SHA1Digest PasswordHash; // TODO new in 5.3.9 - }; - SetupSalt PasswordSalt; // TODO new in 4.2.2 - s32 ExtraDiskSpaceRequired; // LongInt TODO from 4.0.0: Integer64 - s32 SlicesPerDisk; // Integer TODO new in 4.0.0 - - StoredEnum installMode; // (imNormal, imSilent, imVerySilent) TODO removed in 5.0.0, not in 1.2.10, not in 1.3.25 - StoredEnum uninstallLogMode; // (lmAppend, lmNew, lmOverwrite) TODO not in 1.2.10 - StoredEnum uninstallStyle; // (usClassic, usModern) TODO removed in 5.0.0, not in 1.2.10, not in 1.3.25 - StoredEnum dirExistsWarning; // (ddAuto, ddNo, ddYes) TODO not in 1.2.10 - StoredEnum restartComputer; // (rcAuto, rcNo, rcYes) TODO only in [3.0.0, 3.0.3)? - StoredEnum privilegesRequired; // (prNone, prPowerUser, prAdmin) TODO new in 3.0.4 - StoredEnum showLanguageDialog; // (slYes, slNo, slAuto) TODO new in 4.0.10 - StoredEnum languageDetectionMethod; // (ldUILanguage, ldLocale, ldNone) TODO new in 4.0.10 - StoredEnum compressMethod; // CompressionMethod TODO new in 4.1.5 - StoredFlags architecturesAllowed, architecturesInstallIn64BitMode; // set of SetupProcessorArchitecture TODO new in 5.1.0 - - s32 signedUninstallerOrigSize; // LongWord TODO only in [5.2.1, 5.3.10) - u32 signedUninstallerHdrChecksum; // DWORD TODO only in [5.2.1, 5.3.10) - - StoredEnum disableDirPage, disableProgramGroupPage; // new in 5.3.3 - - u32 UninstallDisplaySize; // Cardinal TODO new in 5.3.6 - - StoredFlags options; // set of SetupHeaderOption - -}; -*/ - -// --------------------------------------------------------------------------------------- - -/* TODO remove: - * - TSetupHeader - * - TSetupVersionData - * - TSetupHeaderOption - * - TSetupProcessorArchitecture - * - SetupHeaderStrings - * - SetupID - * - TSetupID - */ - -/* - -template -struct enum_size { }; -#define ENUM_SIZE(Enum, Size) \ - template <> struct enum_size { static const size_t value = (Size); } -#define ENUM_SIZE_LAST(Enum, Last) \ - ENUM_SIZE(Enum, (Last) + 1) -#define ENUM_SIZE_AUTO(Enum) \ - ENUM_SIZE(Enum, Enum ## __End) - -template -class EnumSet { - -public: - - typedef Enum enum_type; - static const size_t count = enum_size::value; - -private: - - typedef void(*unspecified_boolean_type)(); - typedef void(*zero_type)(); - - typedef typename std::bitset type; - - type value; - - EnumSet(type initial) : value(initial) { } - - -public: - - EnumSet() { } - - EnumSet(zero_type * zero) : value(0) { } - - EnumSet(enum_type flag) : value(0) { value.set(flag); } - - EnumSet(const EnumSet & other) : value(other.value) { } - - operator unspecified_boolean_type() const { - return reinterpret_cast(value.any()); - } - - static EnumSet load(type value) { - return EnumSet(value); - } - - EnumSet & set() { - value.set(); - return *this; - } - - bool test(enum_type flag) const { - return value.test(flag); - } - - EnumSet operator&(EnumSet o) const { return EnumSet(value & o.value); } - EnumSet operator|(EnumSet o) const { return EnumSet(value | o.value); } - EnumSet operator~() const { return EnumSet(~value); } - - EnumSet & operator&=(EnumSet o) { value &= o.value; return *this; } - EnumSet & operator|=(EnumSet o) { value |= o.value; return *this; } - - type bitset() { - return value; - } - -}; - -template -static std::ostream & operator<<(std::ostream & os, EnumSet rhs) { - return os << rhs.bitset(); -} - - - - - -STORED_ENUM_MAP(UninstallLogModeMapper, lmUnknown, lmAppend, lmNew, lmOverwrite); -STORED_ENUM_MAP(DirExistsWarningMapper, ddUnknown, ddAuto, ddNo, ddYes); - -template -struct StoredEnumType { - - static const size_t bits = boost::static_unsigned_max<8, next_power_of_two::value >::value >::value; - - typedef typename boost::uint_t::exact type; - -}; -template <> -struct StoredEnumType<0> { - - static const size_t bits = 8; - - typedef typename boost::uint_t::exact type; - -}; - -template -struct StoredFlagBits { - - static const size_t value = boost::static_unsigned_max<8, next_power_of_two::value >::value; - -}; -template -struct StoredFlagType { - - static const size_t bits = StoredFlagBits::value; - - typedef typename boost::uint_t::exact type; - -}; -template -struct StoredFlagType::value > 64 )>::type> { - - static const size_t bits = StoredFlagBits::value; - - typedef typename std::bitset type; - -};*/ - -/* -template ::type> -struct StoredEnum { - - typedef Type stored_type; - typedef typename EnumValueMap::enum_type enum_type; - typedef EnumValueMap map; - - stored_type value; - - StoredEnum() { } - StoredEnum(stored_type inital) : value(inital) { } - - enum_type get() const { - - for(size_t i = 0; i < map::count; i++) { - if(value == i) { - return map::values[i]; - } - } - - return map::default_value; - } - - operator enum_type() const { - return get(); - } - -};*/ -/* -template ::type> -struct StoredFlags { - - typedef Type stored_type; - typedef typename EnumValueMap::enum_type enum_type; - typedef EnumSet flag_type; - typedef EnumValueMap map; - - stored_type value; - - StoredFlags() { } - StoredFlags(stored_type inital) : value(inital) { } - - flag_type get() const { - - stored_type imask = 0; - stored_type omask = 0; - for(size_t i = 0; i < map::count; i++) { - imask |= stored_type(map::values[i] == i) << i; - omask |= stored_type(map::values[i] != i) << i; - } - - flag_type result = flag_type::load(value & imask); - - if(omask) { - - stored_type tmp = value & omask; - - for(size_t i = 0; i < map::count; i++) { - if(tmp & (stored_type(1) << i)) { - result |= map::values[i]; - } - } - - } - - return result; - } - - operator flag_type() const { - return get(); - } - - static stored_type get_imask() { - - stored_type imask = 0; - for(size_t i = 0; i < map::count; i++) { - imask |= stored_type(map::values[i] == i) << i; - } - - return imask; - } - - static stored_type get_omask() { - - stored_type omask = 0; - for(size_t i = 0; i < map::count; i++) { - omask |= stored_type(map::values[i] != i) << i; - } - - return omask; - } - -};*/ - -//#pragma pack(pop) diff --git a/src/SetupLoader.hpp b/src/SetupLoader.hpp index 528a14b..cdd6212 100644 --- a/src/SetupLoader.hpp +++ b/src/SetupLoader.hpp @@ -1,8 +1,11 @@ +#ifndef INNOEXTRACT_SETUPLOADER_HPP +#define INNOEXTRACT_SETUPLOADER_HPP + #include #include -#include "Types.h" +#include "Types.hpp" enum ChecksumMode { ChecksumAdler32, @@ -45,3 +48,5 @@ private: static bool getOffsetsAt(std::istream & is, Offsets & offsets, size_t pos); }; + +#endif // INNOEXTRACT_SETUPLOADER_HPP diff --git a/src/SetupLoaderFormat.hpp b/src/SetupLoaderFormat.hpp index b2d690b..54d0ad6 100644 --- a/src/SetupLoaderFormat.hpp +++ b/src/SetupLoaderFormat.hpp @@ -1,5 +1,5 @@ -#include "Types.h" +#include "Types.hpp" #pragma pack(push,1) diff --git a/src/StoredEnum.hpp b/src/StoredEnum.hpp new file mode 100644 index 0000000..33a850a --- /dev/null +++ b/src/StoredEnum.hpp @@ -0,0 +1,196 @@ + +#ifndef INNOEXTRACT_STOREDENUM_HPP +#define INNOEXTRACT_STOREDENUM_HPP + +#include +#include +#include + +#include "Types.hpp" +#include "LoadingUtils.hpp" +#include "Enum.hpp" +#include "Output.hpp" + +template +struct EnumValueMap { + + typedef Enum enum_type; + typedef Enum flag_type; + +}; + +#define STORED_ENUM_MAP(MapName, Default, ...) \ +struct MapName : public EnumValueMap { \ + static const flag_type default_value; \ + static const flag_type values[]; \ + static const size_t count; \ +}; \ +const MapName::flag_type MapName::default_value = Default; \ +const MapName::flag_type MapName::values[] = { __VA_ARGS__ }; \ +const size_t MapName::count = ARRAY_SIZE(MapName::values) + +#define STORED_FLAGS_MAP(MapName, Flag0, ...) STORED_ENUM_MAP(MapName, Flag0, Flag0, ## __VA_ARGS__) + +template +struct StoredEnum { + + u32 value; + +public: + + typedef Mapping mapping_type; + typedef typename Mapping::enum_type enum_type; + + static const size_t size = Mapping::count; + + inline StoredEnum(std::istream & is) { + value = loadNumber(is); // TODO use larger types for larger enums + } + + enum_type get() { + + if(value < size) { + return Mapping::values[value]; + } + + warning << "warning: unexpected " << EnumNames::name << " value: " << value; + + return Mapping::default_value; + } + +}; + +template +class StoredBitfield { + + typedef u8 base_type; + + static const size_t base_size = sizeof(base_type) * 8; + static const size_t count = (Bits + (base_size - 1)) / base_size; // ceildiv + + base_type bits[count]; + +public: + + static const size_t size = Bits; + + inline StoredBitfield(std::istream & is) { + for(size_t i = 0; i < count; i++) { + bits[i] = loadNumber(is); + } + } + + inline u64 getLowerBits() const { + + BOOST_STATIC_ASSERT(sizeof(u64) % sizeof(base_type) == 0); + + u64 result = 0; + + for(size_t i = 0; i < std::min(sizeof(u64) / sizeof(base_type), count); i++) { + result |= (u64(bits[i]) << (i * base_size)); + } + + return result; + } + + inline std::bitset getBitSet() const { + + static const size_t ulong_size = sizeof(unsigned long) * 8; + + BOOST_STATIC_ASSERT(base_size % ulong_size == 0 || base_size < ulong_size); + + std::bitset result(0); + for(size_t i = 0; i < count; i++) { + for(size_t j = 0; j < ceildiv(base_size, ulong_size); j++) { + result |= std::bitset(static_cast(bits[i] >> (j * ulong_size))) + << ((i * base_size) + (j * ulong_size)); + } + } + return result; + } + +}; + +template +class StoredFlags : private StoredBitfield { + +public: + + typedef Mapping mapping_type; + typedef typename Mapping::enum_type enum_type; + typedef Flags flag_type; + + inline StoredFlags(std::istream & is) : StoredBitfield(is) { } + + flag_type get() { + + u64 bits = this->getLowerBits(); + flag_type result = 0; + + for(size_t i = 0; i < this->size; i++) { + if(bits & (u64(1) << i)) { + result |= Mapping::values[i]; + bits &= ~(u64(1) << i); + } + } + + if(bits) { + warning << "unexpected " << EnumNames::name << " flags: " << std::hex << bits << std::dec; + } + + return result; + } + +}; + +template +class StoredFlagReader { + +public: + + typedef Enum enum_type; + typedef Flags flag_type; + + std::vector mappings; + + void add(enum_type flag) { + mappings.push_back(flag); + } + + + flag_type get(std::istream & is) { + + u64 bits = 0; + + typedef u8 stored_type; + static const size_t stored_bits = sizeof(stored_type) * 8; + for(size_t i = 0; i < ceildiv(mappings.size(), stored_bits); i++) { + bits |= u64(load(is)) << (i * stored_bits); + } + + std::cout << "read " << mappings.size() << " flags: " << std::hex << bits << std::dec << std::endl; + + flag_type result = 0; + + for(size_t i = 0; i < mappings.size(); i++) { + if(bits & (u64(1) << i)) { + result |= mappings[i]; + bits &= ~(u64(1) << i); + } + } + + if(bits) { + warning << "unexpected " << EnumNames::name << " flags: " << std::hex << bits << std::dec; + } + + return result; + } + +}; + +template +class StoredFlagReader > : public StoredFlagReader { }; + +typedef StoredBitfield<256> CharSet; + +#endif // INNOEXTRACT_STOREDENUM_HPP diff --git a/src/Types.h b/src/Types.hpp similarity index 73% rename from src/Types.h rename to src/Types.hpp index ab31ca0..2b690b3 100644 --- a/src/Types.h +++ b/src/Types.hpp @@ -1,4 +1,7 @@ +#ifndef INNOEXTRACT_TYPES_HPP +#define INNOEXTRACT_TYPES_HPP + #include #include @@ -14,3 +17,5 @@ typedef uint64_t u64; typedef u32 Color; typedef std::ios_base strm; + +#endif // INNOEXTRACT_TYPES_HPP diff --git a/src/Version.hpp b/src/Version.hpp index 6c4bac2..b4b4af5 100644 --- a/src/Version.hpp +++ b/src/Version.hpp @@ -5,7 +5,7 @@ #include #include -#include "Types.h" +#include "Types.hpp" typedef u32 InnoVersionConstant; #define INNO_VERSION_EXT(a, b, c, d) ((u32(a) << 24) | (u32(b) << 16) | (u32(c) << 8) | u32(d)) diff --git a/src/BitfieldConverter.hpp b/src/misc/BitfieldConverter.hpp similarity index 100% rename from src/BitfieldConverter.hpp rename to src/misc/BitfieldConverter.hpp diff --git a/src/UnDeflate.cpp b/src/misc/UnDeflate.cpp similarity index 100% rename from src/UnDeflate.cpp rename to src/misc/UnDeflate.cpp diff --git a/test.cpp b/src/misc/test.cpp similarity index 100% rename from test.cpp rename to src/misc/test.cpp