Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Portable unpacking tool for Inno Setup installers

branch: master
README
* uninno *

0. Contents

   1. Introduction
   2. Copyright
   3. Usage
   4. Development
   5. Links


1. Introduction

uninno is a portable unpacking tool for Inno Setup (IS) installers.

Inno Setup is a popular tool for creating software package installers for the
Microsoft Windows operating system. It was written in Delphi by Jordan Russell,
who released under an open source licence.

Other unpacking tools exist, but they are based on the original Inno Setup
source code. As the usual target platform for such installers is
Windows, not much effort has been made to make unpackers portable to other
operating systems.

There are cases however, where there is a legitimate motivation to extract the
installable files on other platforms: One such example is the redistribution of
older software, for which alternative or ported versions exist. These normally
don't include required data files, as those are covered by a different
license than the ported software itself. See the links for (legal) distributors
of such software.


2. Copyright

uninno and all its components are

Copyright (C) 2012 by Gregor Riepl <onitake@gmail.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.
    
    Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The data extraction routines are loosely based on the Inno Setup source code,
but entirely rewritten due to large differences in programming languages and
to improve portability. Some data structures may be reproduced in comments to
help with reimplementation. These will be removed when implementation and
testing is complete.
See http://www.jrsoftware.org/files/is/license.txt for the Inno Setup license.

Starting with commit 8ddd28f5b9e8ff68516065da0843459d44063739, new data
structure parsers are autogenerated by a script, which processes the InnoSetup
source. A second script to check out the InnoSetup git repository and attach
previous versions only available as zip archives is provided.


3. Usage

At its current stage, uninno is provided mainly as a library for dissecting
and analyzing Inno Setup installers. For quick-and-dirty extraction, run
the extract.pl tool on your installer:

$ ./extract.pl setup.exe

Output will be sent to /tmp/uninno.

To support various compression methods, the Perl modules from IO-Compress are
required, as well as the command line utility xz from xz-utils. IO-Compress
does not work with non-standard or raw LZMA1 streams, so we have to rely on
the external program for now.


4. Development

uninno consists of a bunch of Perl packages that handle different stages of the
analysis and extractiong process. Dissection of the installer executable is
provided by Win::Exe, which has some submodules for each of the PE's parts.
Setup::Inno provides a frontend for parsing the setup.0 (metadata) and setup.1
(compressed files) parts of the Inno Setup installer.

To improve code reuse and facilitate handling of all the installer versions,
all version-specific code is represented in a (linear) class hierarchy, spanning
from a base class with simple code stubs over the first open source Inno Setup
release (2.0.8) up to the most recent version. Each class in the hierarchy has
override points that implement data structures, decompression and custom
handling required for this version or its descendants.

Version numbers are coded in 4 digits: x.y.z -> xyzz. The last version part has
two digits and is zero padded. Example: 2.0.8 -> 2008

To find the override point of a method in the hierarchy, use the following code:
sub findovr {
	my ($method, $basever) = @_;
	require "Setup/Inno/Struct$basever.pm";
	my @classes = ("Setup::Inno::Struct$basever");
	while (@classes) {
		my $class = shift(@classes);
		no strict 'refs';
		unshift(@classes, @{$class . '::ISA'});
		my $fqn = $class . '::' . $method;
		if (defined(&{$fqn})) {
			return $class;
		}
	}
}
# Finds out which class overrides ParseOffsetTable, starting from Struct5200
print(findovr('ParseOffsetTable', '5200') . "\n");

Many of the data blocks use LZMA compression, but in a slightly non-standard
format that IO::Uncompress::UnLzma doesn't understand. Due to this, a little
trick is being used: Data is first copied out to a temporary file, which is
then streamed through the command line xz program from xz-utils. Regular
LZMA1 streams are prepended by a header containing the compression parameters,
the dictionary size and a 64 bit length, which can be negative to signal an
unknown stream size. The Inno Setup LZMA format starts with the same parameters,
but leaves out the stream size. IO::Uncompress::UnLzma seems to be under
development, so compatibility with raw streams is possible in the future.

Starting with support for InnoSetup 5.5.0, a new approach is used to create the
various structure parsers. Using a custom Delphi grammar based on an old edition
of the Delphi Language Guide, Projects/Struct.pas is processed and dissected.
Then, a Perl module is generated that can parse binary data represented by the
data structures in that file. The grammar can be found in DelphiGrammar.pm,
the code for the generator in ParserGenerator.pm.

Newer editions of the guide didn't include any formal grammar; it is also
incomplete and in some parts erroneous. Careful simplification and testing was
undertaken to make the grammar successfully parse all versions of Struct.pas.

To generate a new parser, you need to install Marpa::R2. You also need the
specific InnoSetup Struct.pas you'd like to implement support for.
Run:
makeparser.pl
	--input /path/to/innosetup/Projects/Struct.pas
	--output StructParser.pm
	--unicode
	--type TSetupHeader --type TSetupLanguageEntry
	--type TSetupCustomMessageEntry --type TSetupPermissionEntry
	--type TSetupTypeEntry --type TSetupComponentEntry --type TSetupTaskEntry
	--type TSetupDirEntry --type TSetupFileEntry --type TSetupIconEntry
	--type TSetupIniEntry --type TSetupRegistryEntry --type TSetupDeleteEntry
	--type TSetupRunEntry --type TSetupFileLocationEntry
This will just generate the raw parser routines.

Complete parser class generation can also be simplified by using makestruct.pl.
Note that you need to clone the InnoSetup git repository first.
Optionally, you may also import the older sources, if you want to generate
a parser before IS 5.4.3. Use makeissrc.pl to automate this task.

As an example of makestruct usage, run:
makestruct.pl
	--src /path/to/innosetup
	--version 5.5.0u
	--base Setup::Inno::Struct5309
specifying the source code path, the version number (u at the end signifies
a Unicode version) and the base class you want to use.
Output will go to Struct5500u.pm in this case, which needs to be put into
Setup/Inno/ to make Inno.pm find it.


5. Links

Inno Setup: http://www.jrsoftware.org/isinfo.php
innounp: http://innounp.sourceforge.net/
Good Old Games: http://www.gog.com (they sell DRM-free digital copies of vintage
PC games, their installer is built with Inno Setup 5.2.3)
Object Pascal Language Guide for Delphi: http://tinyurl.com/nowcn6c
Something went wrong with that request. Please try again.