Windows Installer Hacking
This page explains how to modify a Windows installer EXE (the big, >70 MB one which contains everything).
Contents
Why?
Normally this is a bad idea, and it is better to build OOo from scratch yourself. However, this may not be possible for various reasons, e.g. if:
- You don't have the (non-Free) toolchain available to build OOo.
- You're modifying a non-Free OOo derivative and don't have the source.
- You don't have the time and resources available to build OOo
- etc.
OOo_2.0_Windows_install_en-US.exe
This is an NSIS self-extracting installer. It contains the following structure:
openofficeorg1.cab openofficeorg2.cab openofficeorg3.cab openofficeorg4.cab openofficeorg20.msi instmsia.exe instmsiw.exe licenses/ readmes/ setup.exe setup.ini
In the OOo 2.0 build process it is built from its contents using a command (at "call_nsis" in solenv/bin/modules/installer/download.pm) which does something like the following:
/cygdrive/c/Program\ Files/NSIS/makensis.exe c:/ooo2/ooo-build/build/ooo680-m3/instsetoo_native/wntmsci10.pro/OpenOffice/nsis/en-US/downloadtemplate.nsi
The file
downloadtemplate.nsi
contains instructions for building the .exe. Its directory also contains
English_pack.nsh English_pack.nlf
which both consist of text strings in the installer language and are referenced from downloadtemplate.nsi. (Various .ico and .bmp files, located outside the directory, are also referenced).
CAB files
These contain the actual files which get extracted. Although CAB files can apparently store a directory tree structure, these ones are flat. The filenames inside the CAB are often, but not always, the same as the names when installed.
N.B. The order in which files are stored is very important!
cabextract -l # lists the contents of a cab file. makecab.exe /F blah.ddf # Create CAB from blah.ddf, a spec+filelist
The "blah.ddf" file can be generated with a perl script like this:
#!/usr/bin/perl -w # # Files to pack: c:\msi\files # Output file path is relative to that directory # Temporary work space: c:\msi\makecabtemp # Usage: perl make-ddf.pl (list of names of files to pack, in order, without path) # print <<EOF; .Set CabinetName1=../out.cab .Set ReservePerCabinetSize=128 .Set MaxDiskSize=CDROM .Set CompressionType=LZX .Set Compress=ON .Set CompressionLevel=2 .Set Cabinet=ON .Set DiskDirectoryTemplate=c:/msi/makecabtemp EOF for my $file (@ARGV) { print qq("c:\\msi\\files\\$file" $file\n); }
Some files in the CABs may not actually get installed: See Component.idt below.
MSI file
This is a relational database which controls the installation process. It can be dumped into tab-separated text files (*.idt), one per table, using
MsiDb.Exe -e -d blah.msi -f c:\text_file_dest *
The text files can be dumped back into a new MSI like this:
MsiDb.Exe -i -d blah_new.msi -f c:\text_file_dest *.idt
(N.B. In both cases, be sure to surround the * in quotes if you're using a UNIX shell)
If you edit these text files, you have to be pretty careful, because there is all sorts of referrential integrity to preserve between tables. To modify the install, some tables are particularly important:
File.idt
This is a list of files which *potentially* can be installed.
- File is the name of the file in the archive.
- Each file is part of a Component.
- FileSize speaks for itself.
- Sequence is the order in which the files appear in the CABs, and the
installer will *fail* if it is not correct. (The Sequence is across all CAB files, so for instance the first file in CAB 3 has the Sequence number one higher than the last file in CAB 2).
Directory.idt
Defines directories per feature component
Media.idt
Specifies the CABs from which to obtain files. Crucially, this specifies the file number ranges contained within each CAB, so if you add any files you will probably have to alter this.
Feature.idt
Defines Features, i.e. groupings of functionality which can be selected in the installer.
FeatureComponent.idt
Each Feature is a set of components.
Component.idt
Specifies into which directory a component is installed (relative to Directory.idt), etc. KeyPath is the First file in the component (in Sequence order) (?)
Full paths of executables
- C:\Program Files\Microsoft Platform SDK\Bin\MsiDb.Exe
- C:\WINDOWS\system32\makecab.exe (on Windows XP)
- cabextract - UNIX (or cygwin) program