MicrosoftInstaller

The Microsoft Installer

The Microsoft Installer (aka MSI) is a scriptable installer packaged with Windows 2000/XP, and available as a redistributable component for Windows 9x. It is used by various (mainly Microsoft) software to package an installation. The installation may be contained in a single .msi database file, or the database maybe augmented by other installation files.

Microsoft's codename for the Microsoft Installer (aka the Windows Installer) was Darwin. This is sometimes refered to in the Platform SDK.

Examples of software that use the Microsoft Installer are:

  • Microsoft Office 2000, XP and 2003
  • iTunes
  • Quicken 2004
  • MSN Messenger

The Microsoft Installer consists of a front end executable (msiexec.exe) and a dll (msi.dll). The front end is responsible for passing of a command line, setting the install parameters and calling into the dll to do most work. Both of these are implemented in Wine.

The installer can be run as a windows service (MSIServer), which is accessed through a COM interface. This feature is not yet implemented in Wine.

There major components of the Microsoft Installer architecture are:

  • the database
  • the scripting engine and actions
  • the user interface
  • installer data stored in the registry

The MSI Database

There's a short overview of the msi database format on MSDN.

The MSI Database is a structured storage file, the format of which is mostly undocumented. It contains a number of streams. The streams are named such that the names of tables and binaries do not overlap. The streams can be:

  • tables (of a simple database)
  • binaries (dlls, executables, bitmaps, etc)
  • summary information

The database can be queried using a simple subset of SQL. These queries are built and executed using the msi.dll export functions MsiDatabaseOpenView, MsiViewExecute, MsiViewFetch, and MsiViewClose.

Each table in the database is a single stream in the structured storage file. The stream names are mapped from the name of the table, using a simple 8bit <-> 6bit encoding, similar to base64 encoding.

Strings in the database are represented by an number, which is an offset into the string table. The string can be determined using the streams _StringData and _StringPool. The offset points to two 2 byte integers in _StringPool, one being the length of the string in bytes, and the other the number of occurences. The string is found in _StringData by adding up all the previous lengths and generating an offset.

If an entry int the _StringPool table has zero length, and a non-zero reference count, the refence count is instead treated as the high word of the length of the following string. This allows string lengths of over 64k.

All general tables contain 2 or 4 byte numbers that are either offsets into the string table, or just integers. The high bit of an integer value means that it is positive, not negative.

All the values in the first column are stored sequentially, followed by all the values in the second column, etc. This means that row inserts cannot be performed without moving most of the data in a table... the MSI database format appears to be optimized for space, not speed.

The type of an field is defined by the "Type" field in the "_Tables" table. It also defines the size of each column in the database, it's type, encoding (string/number) and whether it is a primary key or not.

If a stream is saved into a database field, it is stored as a normal stream in the structured storage file. The encoding of the stream name is done such that it doesn't clash with table names.

The stream corresponding to a table may be missing. This is interpretted by the MSI database engine as being an empty table, not an error.

The MSI registry

The installer keeps a record of Products, Components and Features in the registry. These are mostly stored in the key HKLM\Software\Microsoft\Windows\CurrentVersion\Installer on Windows 9x, and in HKCR\Installer for Windows 2000/XP.

MSI uses the registry extensively to record what is installed, and what depends upon what.

GUIDs used by MSI in the registry are represented in one of three ways:

  • ole32 form {xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx}
  • squished form, removing the - and { from the above. eg. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  • base85 form eg. xxxxxxxxxxxxxxxxxxxx

Base 85 form uses 5 of the following characters to represent a DWORD:

  • !$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{}~

This works seeing that 855 > 232.

MSI Dialogs

All the dialogs that MSI can create during an install must be entered into the Dialog table in the MSI database. Each dialog can have any number of controls, and they must be entered into the Control table.

There are a number of types of dialog control.

  • Text, Bitmap and Icon - are static things

  • Edit, PathEdit and ScrollableText are different types of editable things

  • RadioButton, PushButton and CheckBox are different types of clickable things

These are implemented in 'dlls/msi/dialogs.c'.

MicrosoftInstaller (last edited 2008-05-03 02:18:02 by nathan.n)