Microsoft Installer Custom Actions User Impersonation

Microsoft Installer Custom Actions User Impersonation

Problem

When creating an installer with custom actions you might run into some security issues when executing it on a Windows Vista/7/2008 or later OS.
This is because custom actions will be executed in the context of the user running the Windows Installer Service being the SYSTEM user.
This behavior is enforced from Windows Vista on and can give you authorization problems for certain tasks you want to perform in your custom actions.

Solution

To overrule this default behavior and run the custom actions as the impersonated user that is executing the MSI we will have to flip themsidbCustomActionTypeNoImpersonate bit that is on by default.
In a Visual Studio Setup project it is however not possible to set this flag through the Properties Window.
To solve this we must create a post-build script that will flip this bit:

// CustomAction_Impersonate.js
// Performs a post-build fixup of an msi to change all deferred custom actions to Impersonate
// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;

var msiViewModifyInsert         = 1
var msiViewModifyUpdate         = 2
var msiViewModifyAssign         = 3
var msiViewModifyReplace        = 4
var msiViewModifyDelete         = 6

var msidbCustomActionTypeInScript       = 0x00000400;
var msidbCustomActionTypeNoImpersonate  = 0x00000800

if (WScript.Arguments.Length != 1)
{
       WScript.StdErr.WriteLine(WScript.ScriptName + ” file”);
       WScript.Quit(1);
}

var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject(“WindowsInstaller.Installer”);
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);

var sql
var view
var record

try
{
       sql = “SELECT Action, Type, Source, Target FROM CustomAction”;
       view = database.OpenView(sql);
       view.Execute();
       record = view.Fetch();
    //Loop through all the Custom Actions
       while (record)
       {
           if (record.IntegerData(2) & msidbCustomActionTypeInScript)
           {
               //We must flip the msidbCustomActionTypeNoImpersonate bit only for deferred custom actions
               record.IntegerData(2) = record.IntegerData(2) & ~msidbCustomActionTypeNoImpersonate;
              view.Modify(msiViewModifyReplace, record);
           }
        record = view.Fetch();
       }

       view.Close();
       database.Commit();
}
catch(e)
{
       WScript.StdErr.WriteLine(e);
       WScript.Quit(1);
}

This script file (CustomAction_Impersonate.js) must be placed in the same folder as your setup project (Setup.vdproj) and add the following PostBuildEvent in your setup project:
cscript.exe “$(ProjectDir)CustomAction_Impersonate.js” “$(BuiltOuputPath)”

Build and run your setup project and you will notice that all the custom actions will now run as the impersonated user that executes the MSI.

Author: Christophe



Working at i8c

i8c is a system integrator that strives for an informal atmosphere between its employees, who have an average age of approx 30 years old. We invest a lot of effort in the professional development of each individual, through a direct connection between the consultants and the management (no multiple layers of middle management). We are based in Kontich, near Antwerp, but our customers are mainly located in the triangle Ghent-Antwerp-Brussels and belong to the top 500 companies in Belgium (Securex, Electrabel, UCB, etc…).

Quality Assurance

i8c is committed to delivering quality services and providing customer satisfaction. That’s why we invested in the introduction of a Quality Management System, which resulted in our ISO9001:2000 certification. This guarantees that we will meet your expectations, as a reliable, efficient and mature partner for your SOA & integration projects.

i8c - ISO9001-2015