Patch Applicability

When installing a patch package, Windows Installer first determines if the patch is applicable. Depending on how the patch is installed, this happens a little differently. Windows Installer can determine the list of applicable products, or it can be told to which products the patch should be applied.

Possible products

To have Windows Installer determine to which products the patch applies, you can execute msiexec.exe with /update or /p as shown in the following example.

msiexec.exe /update patch.msp

Windows Installer will enumerate the list of ProductCodes in the patch’s Template summary property. The same behavior is true when calling the MsiApplyPatch() function or the MsiApplyMultiplePatches() function when the second parameter is null.

You can also tell Windows Installer to which product the patch should applied using /package or /i as shown in the following example.

msiexec.exe /package {ProductCode} /update patch.msp

For the specified ProductCode or product package, Windows Installer will build the PATCH property and pass that in the command line similar to executing msiexec.exe as shown in the following example. When using the PATCH property, the full paths to each patch must be supplied.

msiexec.exe /package {ProductCode} PATCH=fullpathpatch.msp

Windows Installer will evaluate each patch against the specified product. However, if installing the patch or patches using MsiApplyMultiplePatches() with a specific ProductCode, Windows Installer will modify the PATCH property to list only the patch packages with the specified ProdutCode in their Template summary property. If you’re not sure which patches apply to a product, this may be desirable behavior. If you pass in the PATCH property yourself and even one patch does not apply to the specified ProductCode, Windows Installer will terminate and return ERROR_PATCH_TARGET_NOT_FOUND (1642).

Verifying applicability

Once the list of patches has been passed into the installation session, Windows Installer will enumerate the transforms in each patch being applied. If a minor upgrade patch is being installed, Windows Installer will also enumerate the transforms in patches that have already been applied because minor upgrade may change which patches are applicable.

Within a patch package are sets of transforms: there is an authoring transform that describes the changes to the product, and a patch transform that describes how to install the patch and which files are updated. These transforms have the same name except the patch transform name begins with a hash (#).

Windows Installer will enumerate each authoring transform, using the following applicability information from their summary information stream.

The transform validation bits in the Character Count summary property determine which other summary properties are relevant. The typical validation bits of 0x0922 specify that the target ProductCode and UpgadeCode are equal to those specified in the Revision Number summary property of the transform, and that the full ProductVersion is equal to the value also in the Revision Number summary property. It’s also important to note that Windows Installer only validates up to the first three fields of the ProductVersion. The fourth field can be changed freely in a small update as a means of tracking and diagnosing updates.

If the ProductLanguage was validated, the ProductLanguage of the target product must match the value in the Template summary property.

When an authoring transform has been validated as applicable to the current product, the related patch transform is assumed to be applicable (validation bits are ignored). The remaining transforms in a patch are ignored, though Windows Installer will still log verbose validation information for each remaining transform.

If a valid transform is found within a patch, the patch is applicable to the product. That still doesn’t mean the patch will be applied, however, since the patch must still be sequenced and supersedence determined. But if a patch is applicable, it will at least be registered to the product. This means that it may be applied in the future if other patches are installed or removed from the product, and that it will be uninstalled with the product. However, since a single patch package is cached for all applicable products, the patch package itself is not deleted from the system until all products to which it’s registered are uninstalled or the patch is uninstalled from all applicable products.

Once all applicable patched are determined, a verbose log will display applicable, obsolesced, superseded, and invalid patches as shown in the following log example.

MSI (c) (88:38) [21:17:01:707]: Final Patch Application Order:
MSI (c) (88:38) [21:17:01:707]: {C26A5DDB-E2C5-4D2E-BC6E-449CBA57184E} -
MSI (c) (88:38) [21:17:01:707]: {A4AC638D-2C4F-4C9E-8962-9A674E782259} -
MSI (c) (88:38) [21:17:01:707]: {C697D8F7-E77A-4DA1-9CED-3F3E5115400D} - c:UsersTestAppDataLocalTemppatch1.msp
MSI (c) (88:38) [21:17:01:707]: {73F7C9E3-08EC-4910-8D5B-3BF90C07EC1C} -
MSI (c) (88:38) [21:17:01:707]: Other Patches:
MSI (c) (88:38) [21:17:01:707]: Superseded: {B45F8725-6450-44D0-9284-01F321026767} -
MSI (c) (88:38) [21:17:01:707]: Superseded: {B0BB7DD1-D63A-4B73-8E73-6F055CB541AC} -
MSI (c) (88:38) [21:17:01:707]: UnknownAbsent: {402ADF4A-1B3D-4824-AE69-3606DDC2CE70} - c:UsersTestAppDataLocalTemppatch2.msp

The names of the valid transforms are also registered to the product to save time by not re-evaluating applicable patches and transforms again during repair operations. The names of the valid transforms can be retrieved using the MsiGetProductInfo() or MsiGetProductInfoEx() functions with the INSTALLPROPERTY_TRANSFORMS property.

Transforming the database

Windows Installer will not actually modify the target database unless applying the patch to an administrative installation, which is created by using msiexec.exe /a. The vast majority of time, you will install a patch on a client machine.

Windows Installer will create views on the product database transformed by each applied transform. When Windows Installer queries the package for information, typically the transforms will add to, update, or remove data and tables. However, the transform error condition flags will fail the installation if not satisfied. With the typical transform error condition flags of 0x001f, Windows Installer will only err if the transforms attempt to change the database code page.

Order of events

Determining patch applicability and validating transforms always occurs before installation execution begins. Any code that needs to modify the list of patches must execute before installing or updating a product. This includes calling APIs like the MsiInstallProduct() function. Custom actions scheduled to execute during installation cannot modify the list of patches, and returning an error from any custom action added by a patch will terminate the entire installation session.