;----------------------------------------------------------------------------
;    MODULE NAME:   PATCH.TXT
;
;         Author:   Julian Onions
;      $Revision:   1.1  $
;          $Date:   21 Sep 2005 19:23:16  $
;       $Logfile:   C:/DBAREIS/Projects.PVCS/Win32/MakeMsi/patch[JulianOnions].mmh.txt.pvcs  $
;
; DESCRIPTION
; ~~~~~~~~~~~
; Maintained by Julian Onions.
;----------------------------------------------------------------------------


Various macros and general instructions specified here.

-----------------------------------------------------------------------------------------
Patch

This command is used to create or open an MSI PCP file for patch production.

This command takes several parameters:

- The MSI Patch file name
The first positional parameter is the name of the patch being created. This is used
as the name of the file and to fill in some of the fields.

- Template (optional)
This is a patch template to use to build the patch PCP file. If not supplied it defaults to
"template.PCP" which can be copied from the MSI SDK.


- Version (optional)
This sets the minimum installer version the patch will require. If not set, this will be
set to 200 stating the windows installer version 2 is the target. This allows a lot more
flexibilty in some of the tables.

Examples

Start creation of a patch

; include the relevant support file
#include "patch.mmh"

; Open a patch to create MyPatch
<$Patch "MyPatch">


-----------------------------------------------------------------------------------------

/Patch

This command is used to close a patch database previously opened with the Patch command.

-----------------------------------------------------------------------------------------

PatchFamily

This command is used to define a table entry in the patch database for a family.
It is primarily used to link together other tables. It populates the ImageFamilies
table.

This command takes a number of parameters:

- Family (OPTIONAL)
This is the name of the family. Note that with the standard PCP file this field
is constrained to 8 characters. It seems to be used mainly as a linking table however,
so the value is not critical. If not supplied the Patch name supplied in the Patch
command will be used.


- MediaSrc (OPTIONAL)
This fills out the MediaSrcPropName and defaults to empty.
This is not used particularly with version 2 of MSI. More care needs to be taken
if MSI v1 is the target.

- MediaDisk (OPTIONAL)
This parameter sets the MediaDiskId entry in the ImageFamilies record. See the MSI documentation
for various restrictions on its use. It defaults to empty.

- Seq (OPTIONAL)
The parameter sets the FileSequenceStart entry. Again there are various restrictions on
this field if the target is MSI V1. It defaults to 1000.

- DiskPrompt (OPTIONAL)
The parameter sets the DiskPrompt entry in the table. It defaults to empty if not specified.

- VolumeLabel (OPTIONAL)
The parameter sets the VolumeLabel of this table. It defaults to empty.

Example

; include the relevant support file
#include "patch.mmh"
<$Patch "MyPatch" >
    #define Family MyFamily
    <$PatchFamily Family="<$Family>">
    <$PatchImage Key="MyOrig" SrcMsi="srcmsi\MyMSI.msi" Upgraded="MyPatch">
    <$PatchUpgrade Key="MyPatch" NewMsi="patchmsi\MyMSI.msi" Family="<$Family>">
    <$PatchSequence Family="<$Family>" Version="1.0.1">
<$/Patch>


-----------------------------------------------------------------------------------------

PatchUpgrade


This command adds an upgrade record to the patch database. Its is possible to have several
of these records, although a basic patch will have only one. It populates the UpgradedImages
records.


It has several parameters:

- NewMsi (REQUIRED)
This is a path name to an MSI file that is the target for the patch. So the after file
in a before and after msi build.

- Family (OPTIONAL)
This the patch family name. It will default to the name of the patch
specified in the Patch command if not supplied. It should match the
name you used in PatchFamily if you specified one.

- Key (OPTIONAL)
This is the key for this table, and defaults to the name of the
patch with "_fixed" appended if not supplied. It should match the Upgraded entry
given in the PatchImage line.

- PatchMsi (OPTIONAL)
An optional pathname to an MSI for additional properties. See the MSI documentation
for more details. It defaults to empty.

- SymbolPaths (OPTIONAL)
This is a semi-colon separated list of folders that will be searched for .PDB fies
relating to any .EXE files that are to be patched. This can result in smaller patch images.
It defaults to empty.

Example
; include the relevant support file
#include "patch.mmh"
<$Patch "MyPatch" >
    #define Family MyFamily
    <$PatchFamily Family="<$Family>">
    <$PatchImage Key="MyOrig" SrcMsi="srcmsi\MyMSI.msi" Upgraded="MyPatch">
    <$PatchUpgrade Key="MyPatch" NewMsi="patchmsi\MyMSI.msi" Family="<$Family>">
    <$PatchSequence Family="<$Family>" Version="1.0.1">
<$/Patch>

-----------------------------------------------------------------------------------------

PatchImage

This command adds an entry to the patch database relating to the original MSI build.
The before, in a before and after build. There may be more than one PatchImage lines for
a complex patch.

- SrcMsi (REQUIRED)
This is the path to the original MSI file. The base version that the patch will be generated
against.

- Upgraded (REQUIRED)
This is a link to a PatchUpgrade entry. It specifies the key used in that record.

- Key (OPTIONAL)
This is the key for this record. It defaults to the patch name as specified in the Patch command
with the string "Error" appended.

- SymbolPaths (OPTIONAL)
This is a semi-colon separated list of folders that will be searched for .PDB fies
relating to any .EXE files that are to be patched. This can result in smaller patch images.
It defaults to empty.

- Order (OPTIONAL)
This specifies where this record exists in a list of patch targets within this database.
It defaults to 1 which is suitable if only one patch is being built.

- ValidateFlags (OPTIONAL)
This allows various flags to be set to control the patch generation. It defaults to 0x00000922
which is the value recommended in the MSI documentation.

- IgnoreMissing (OPTIONAL)
This allows the patch process to ignore missing files from the MSI images if set to 1.
In this case these files are obviously skipped rather than being examined for changes.
This can speed up the patch generation, but is also subject to error. It defaults to 0.


Example
; include the relevant support file
#include "patch.mmh"
<$Patch "MyPatch" >
    #define Family MyFamily
    <$PatchFamily Family="<$Family>">
    <$PatchImage Key="MyOrig" SrcMsi="srcmsi\MyMSI.msi" Upgraded="MyPatch">
    <$PatchUpgrade Key="MyPatch" NewMsi="patchmsi\MyMSI.msi" Family="<$Family>">
    <$PatchSequence Family="<$Family>" Version="1.0.1">
<$/Patch>


-----------------------------------------------------------------------------------------

PatchSequence

This command allows patch sequencing to be controlled - which is a windows installer version 3
feature.

It has the following parameters:

- Version (REQUIRED)
This specifies the patch order using a version number sequence. Higher version numbers
being applied after earlier versions.


- Family (OPTIONAL)
The family name of the patch. This defaults to the name of the patch sepcified in the
Patch command if not provided.

- ProductCode (OPTIONAL)
This is a GUID that allows the patch to be targeted at a specific product code.
It defaults to empty, which allows the patch sequence to be applied to any applicable
product.

- Attributes (OPTIONAL)
This defaults to 0, which indicates this is a sequential patch. If set to one then
it implies this superceeds a previous patch.

Example
; include the relevant support file
#include "patch.mmh"
<$Patch "MyPatch" >
    #define Family MyFamily
    <$PatchFamily Family="<$Family>">
    <$PatchImage Key="MyOrig" SrcMsi="srcmsi\MyMSI.msi" Upgraded="MyPatch">
    <$PatchUpgrade Key="MyPatch" NewMsi="patchmsi\MyMSI.msi" Family="<$Family>">
    <$PatchSequence Family="<$Family>" Version="1.0.1">
<$/Patch>


-----------------------------------------------------------------------------------------

PatchProperty

This command allows various patch properties to be set. For a complete list
see the MSI documentation. Note that this is not the same as the Property table
that is found in normal MSI files. The table is actually called "Properties" as
opposed to "Property"

It has two parameters
- First parameter positional (REQUIRED)
This is the name of the property that is being set.

- Value (REQUIRED)
This is the value of the property.

Example
    <$PatchProperty "OptimizePatchSizeForLargeFiles" Value=1>


-----------------------------------------------------------------------------------------

PatchMetaData

This is additional information that can be suppleid and used with version 3 of the
windows installer. There are a number of properties that can be set that influence
how the patch is built. They allow the possibility of specifing the patch is removable
as well as giving it a useful name.

It has a number of parameters:


- First parameter positional (REQUIRED)
The name of the patch meta data property. See the MSI documentation for some standard
ones.

- Value (REQUIRED)
The value of the patch meta data.

- Company (OPTIONAL)
This defaults to empty, which specifies the property is a standard one, rather than
a company specific one.

My default, the Patch command fills in a number of these for you, which can be
overridden by #define-ing them. These are shown in the example. See the MSI documentation
for their specific meaning. The CreationTimeUTC meta-data is set to the current time of patch build.



Example:

#define? PATCH_ALLOW_REMOVAL 1
#define? PATCH_MANUFACTURER  MakeMsi
#define? PATCH_URL <$COMPANY_ARP_URL_APPLICATION_UPDATE_INFORMATION>
#define? PATCH_PRODUCTNAME Patch
#define? PATCH_DISPLAYNAME Patch
#define? PATCH_DESCRIPTION Patch
#define? PATCH_CLASSIFICATION Normal Patch Upgrade

...

    <$PatchMetaData "AllowRemoval" Value="<$PATCH_ALLOW_REMOVAL>">
    <$PatchMetaData "ManufacturerName" Value="<$PATCH_MANUFACTURER>">
    <$PatchMetaData "MoreInfoURL" Value="<$PATCH_URL>">
    <$PatchMetaData "DisplayName" Value="<$PATCH_DISPLAYNAME>">
    <$PatchMetaData "Description" Value="<$PATCH_DESCRIPTION>">
    <$PatchMetaData "Classification" Value="<$PATCH_CLASSIFICATION>">
    <$PatchMetaData "CreationTimeUTC" Value="<$PatchBuildTime>">
    <$PatchMetaData "TargetProductName" Value="<$PATCH_PRODUCTNAME>">



-----------------------------------------------------------------------------------------

SimplePatch

This command wraps up the whole patching sequence in one command, for the cases where
the patch being made is a simple one between two MSI files. It uses generated defaults
for most of the fields.

It has the following parameters:
- Name (REQUIRED)
What the patch is to be called. It is used as the parameter internally to the Patch Command.

- BaseMsi (REQUIRED)
The path name of the base MSI build that you want to generate the patch with respect to.

- FinalMsi (REQUIRED)
The path name of the new MSI build that has the new data in it.


Example:
<$SimplePatch Name="<$PatchName>" BaseMsi="basemsi\MYMSI.msi" FinalMsi="updated\MYMSI.msi">

-----------------------------------------------------------------------------------------

Patch Production

There are a confusing number of patch types that are around, and that can be generated.
These include

small updates - this is equivalent to a hot fix, or quick fix. It does not change
the product code, or the version number. There are a number of restrictions on what
can be included in this. No new features and only certain additions can be made.

minor update - this is a small change to the product, equivalent to a service pack or
small upgrade. The product code does not change, but the version number does.

major update - this is almost a full blown reinstall, and the advice is not to bother with
these, but use a full reinstall instead.

To make both the first two types, it is important that things stay the same as much
as possible. This means fixing the productcode GUID, and the component GUIDs.

The productcode can be fixed, using the same mechanism in the TryMeWithFixedIds example.

The componentIds can be fixed using the ComponentId="?" in each component.

Another thing to watch out for is custom actions, in some cases you may need to
skip CA's when installing a patch, which you can control with the condtion
"not PATCH"

You will also require the following from the SDK.
Template.PCP, PatchWiz.dll, mspatchc.dll and MsiMSP.exe


With that preparation, this is one way to go about making a patch.

1. Build your installer as normal with makemsi, and save the results somewhere.

2. Make the changes required to the source material.

3. Build the new installer - updating the version number as required.
At this point it is worth running the MsiDiff command to compare the images and
see what has changed. You need to look at the output carefully to be sure no
componentIds have been changed unexpectedly.

4. Extract both contents to two separate directories using an Admin install. Patching
will only work on uncompressed images. You can do this with the command
msiexec /a "MyInst.msi" TARGETDIR="c:/build/msi1" /q

5. Run the patch .MM file to produce the patch.

This should result in a MSP file which can be applied with the command
   msiexec /p File.MSP REINSTALLMODE=omus REINSTALL=ALL
you may wish to include the paremeters /l*v applypatch.log
to get a verbose trace of the attempt to apply the patch.


