|
From: Rob M. <ro...@us...> - 2007-09-21 07:58:44
|
Update of /cvsroot/wix/wix/src/wix In directory sc8-pr-cvs9.sourceforge.net:/tmp/cvs-serv19110/src/wix Modified Files: Binder.cs Compiler.cs CompilerCore.cs Decompiler.cs Patch.cs Table.cs Uuid.cs wix.csproj wixdll.build Added Files: ComponentRow.cs Log Message: AaronSte: Creating separate Votive and Sconce DLLs for VS 2005 and VS 2008. Adding the VS 2008 SDK source code that is needed to build the VS 2008 Votive and Sconce dlls. HeathS: SFBUG:1789825 - CreationTimeUTC documents wrong format SFFEATURE:1768845 - Patch element should support MinorUpdateTargetRTM attribute SFFEATURE:1735295 - Patch build should add PATCHNEW* properties to patch transform Added support for ignorables to CompareUnit in WixUnit HeathS: SFBUG:1768842 - PatchProperty does not allow Company RobMen: Ensure RegistryKey element never ends up as KeyPath because MSI SDK says it isn't allowed. RobMen: Component guid generation. RobMen: SFBUG:1795309 - respect the rollback flag for the last SQL string like all the other strings. RobMen: SFBUG:1787888 - correctly handle certificates that are in Components that are conditioned out. RobMen: SFBUG:1675194 - loop through all server bindings when searching for a match. Index: Patch.cs =================================================================== RCS file: /cvsroot/wix/wix/src/wix/Patch.cs,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Patch.cs 3 Sep 2007 21:53:29 -0000 1.3 --- Patch.cs 21 Sep 2007 07:58:40 -0000 1.4 *************** *** 9,12 **** --- 9,39 ---- namespace Microsoft.Tools.WindowsInstallerXml { + /// <summary> + /// Values for the OptimizeCA MsiPatchMetdata property, which indicates whether custom actions can be skipped when applying the patch. + /// </summary> + [Flags] + internal enum OptimizeCA + { + /// <summary> + /// No custom actions are skipped. + /// </summary> + None = 0, + + /// <summary> + /// Skip property (type 51) and directory (type 35) assignment custom actions. + /// </summary> + SkipAssignment = 1, + + /// <summary> + /// Skip immediate custom actions that are not property or directory assignment custom actions. + /// </summary> + SkipImmediate = 2, + + /// <summary> + /// Skip custom actions that run within the script. + /// </summary> + SkipDeferred = 4, + } + public class Patch { *************** *** 102,105 **** --- 129,208 ---- } + // populate MSP summary information + Table patchSummaryInfo = patch.EnsureTable(this.tableDefinitions["_SummaryInformation"]); + + // remove any existing data for these fields + for (int i = patchSummaryInfo.Rows.Count - 1; i >= 0; i--) + { + Row row = patchSummaryInfo.Rows[i]; + switch ((SummaryInformation.Patch)row[0]) + { + case SummaryInformation.Patch.ProductCodes: + case SummaryInformation.Patch.TransformNames: + case SummaryInformation.Patch.PatchCode: + case SummaryInformation.Patch.InstallerRequirement: + patchSummaryInfo.Rows.RemoveAt(i); + break; + } + } + + // GUID patch code for the patch. + Row revisionRow = patchSummaryInfo.CreateRow(null); + revisionRow[0] = (int)SummaryInformation.Patch.PatchCode; + revisionRow[1] = patchId; + + // Indicates the minimum Windows Installer version that is required to install the patch. + Row wordsRow = patchSummaryInfo.CreateRow(null); + wordsRow[0] = (int)SummaryInformation.Patch.InstallerRequirement; + wordsRow[1] = ((int)SummaryInformation.InstallerRequirement.Version31).ToString(); + + Row security = patchSummaryInfo.CreateRow(null); + security[0] = 19; //PID_SECURITY + security[1] = "4"; // Read-only enforced + + Table msiPatchMetadataTable = patch.Tables["MsiPatchMetadata"]; + Hashtable metadataTable = new Hashtable(); + if (null != msiPatchMetadataTable) + { + foreach (Row row in msiPatchMetadataTable.Rows) + { + metadataTable.Add(row.Fields[1].Data.ToString(), row.Fields[2].Data.ToString()); + } + + if (metadataTable.Contains("DisplayName")) + { + string comment = String.Concat("This patch contains the logic and data required to install ", metadataTable["DisplayName"]); + + Row title = patchSummaryInfo.CreateRow(null); + title[0] = 2; //PID_TITLE + title[1] = metadataTable["DisplayName"]; + + Row comments = patchSummaryInfo.CreateRow(null); + comments[0] = 6; //PID_COMMENTS + comments[1] = comment; + } + + if (metadataTable.Contains("CodePage")) + { + Row codePage = patchSummaryInfo.CreateRow(null); + codePage[0] = 1; //PID_CODEPAGE + codePage[1] = metadataTable["CodePage"]; + } + + if (metadataTable.Contains("Description")) + { + Row subject = patchSummaryInfo.CreateRow(null); + subject[0] = 3; //PID_SUBJECT + subject[1] = metadataTable["Description"]; + } + + if (metadataTable.Contains("ManufacturerName")) + { + Row author = patchSummaryInfo.CreateRow(null); + author[0] = 4; //PID_AUTHOR + author[1] = metadataTable["ManufacturerName"]; + } + } + // enumerate transforms ArrayList productCodes = new ArrayList(); *************** *** 175,192 **** } ! // populate MSP summary information ! Table patchSummaryInfo = patch.EnsureTable(this.tableDefinitions["_SummaryInformation"]); ! // remove any existing data for these fields ! for (int i = patchSummaryInfo.Rows.Count - 1; i >= 0; i--) { ! Row row = patchSummaryInfo.Rows[i]; ! switch ((SummaryInformation.Patch)row[0]) { ! case SummaryInformation.Patch.ProductCodes: ! case SummaryInformation.Patch.TransformNames: ! case SummaryInformation.Patch.PatchCode: ! case SummaryInformation.Patch.InstallerRequirement: ! patchSummaryInfo.Rows.RemoveAt(i); ! break; } } --- 278,297 ---- } ! // Finish filling tables with transform-dependent data. ! if (metadataTable.Contains("AllowRemoval")) { ! if ("1" == metadataTable["AllowRemoval"].ToString()) { ! ArrayList tables = this.GetPatchUninstallBreakingTables(); ! bool result = true; ! foreach (DictionaryEntry entry in validTransfrom) ! { ! result &= this.CheckUninstallableTransform(entry.Key.ToString(), (Output)entry.Value, tables); ! } ! ! if (!result) ! { ! throw new WixException(WixErrors.PatchNotRemovable()); ! } } } *************** *** 201,280 **** savedbyRow[0] = (int)SummaryInformation.Patch.TransformNames; savedbyRow[1] = String.Join(";", (string[])transformNames.ToArray(typeof(string))); - - // GUID patch code for the patch. - Row revisionRow = patchSummaryInfo.CreateRow(null); - revisionRow[0] = (int)SummaryInformation.Patch.PatchCode; - revisionRow[1] = patchId; - - // Indicates the minimum Windows Installer version that is required to install the patch. - Row wordsRow = patchSummaryInfo.CreateRow(null); - wordsRow[0] = (int)SummaryInformation.Patch.InstallerRequirement; - wordsRow[1] = ((int)SummaryInformation.InstallerRequirement.Version31).ToString(); - - Row security = patchSummaryInfo.CreateRow(null); - security[0] = 19; //PID_SECURITY - security[1] = "4"; // Read-only enforced - - Table msiPatchMetadataTable = patch.Tables["MsiPatchMetadata"]; - if (null != msiPatchMetadataTable) - { - Hashtable metadataTable = new Hashtable(); - foreach (Row row in msiPatchMetadataTable.Rows) - { - metadataTable.Add(row.Fields[1].Data.ToString(), row.Fields[2].Data.ToString()); - } - - if (metadataTable.Contains("AllowRemoval")) - { - if ("1" == metadataTable["AllowRemoval"].ToString()) - { - ArrayList tables = this.GetPatchUninstallBreakingTables(); - bool result = true; - foreach (DictionaryEntry entry in validTransfrom) - { - result &= this.CheckUninstallableTransform(entry.Key.ToString(), (Output)entry.Value, tables); - } - - if (!result) - { - throw new WixException(WixErrors.PatchNotRemovable()); - } - } - } - - if (metadataTable.Contains("DisplayName")) - { - string comment = String.Concat("This patch contains the logic and data required to install ", metadataTable["DisplayName"]); - - Row title = patchSummaryInfo.CreateRow(null); - title[0] = 2; //PID_TITLE - title[1] = metadataTable["DisplayName"]; - - Row comments = patchSummaryInfo.CreateRow(null); - comments[0] = 6; //PID_COMMENTS - comments[1] = comment; - } - - if (metadataTable.Contains("CodePage")) - { - Row codePage = patchSummaryInfo.CreateRow(null); - codePage[0] = 1; //PID_CODEPAGE - codePage[1] = metadataTable["CodePage"]; - } - - if (metadataTable.Contains("Description")) - { - Row subject = patchSummaryInfo.CreateRow(null); - subject[0] = 3; //PID_SUBJECT - subject[1] = metadataTable["Description"]; - } - - if (metadataTable.Contains("ManufacturerName")) - { - Row author = patchSummaryInfo.CreateRow(null); - author[0] = 4; //PID_AUTHOR - author[1] = metadataTable["ManufacturerName"]; - } - } } --- 306,309 ---- *************** *** 828,831 **** --- 857,889 ---- pairedPropertyRow[1] = patchId; + // add PATCHNEWPACKAGECODE to apply to admin layouts + pairedPropertyRow = pairedPropertyTable.CreateRow(null); + pairedPropertyRow.Operation = RowOperation.Add; + pairedPropertyRow[0] = "PATCHNEWPACKAGECODE"; + pairedPropertyRow[1] = patchId; + + // add PATCHNEWSUMMARYCOMMENTS and PATCHNEWSUMMARYSUBJECT to apply to admin layouts + Table _summaryInformationTable = this.patch.Tables["_SummaryInformation"]; + if (null != _summaryInformationTable) + { + foreach (Row row in _summaryInformationTable.Rows) + { + if (3 == (int)row[0]) // PID_SUBJECT + { + pairedPropertyRow = pairedPropertyTable.CreateRow(null); + pairedPropertyRow.Operation = RowOperation.Add; + pairedPropertyRow[0] = "PATCHNEWSUMMARYSUBJECT"; + pairedPropertyRow[1] = row[1]; + } + else if (6 == (int)row[0]) // PID_COMMENTS + { + pairedPropertyRow = pairedPropertyTable.CreateRow(null); + pairedPropertyRow.Operation = RowOperation.Add; + pairedPropertyRow[0] = "PATCHNEWSUMMARYCOMMENTS"; + pairedPropertyRow[1] = row[1]; + } + } + } + return pairedTransform; } Index: CompilerCore.cs =================================================================== RCS file: /cvsroot/wix/wix/src/wix/CompilerCore.cs,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -d -r1.32 -r1.33 *** CompilerCore.cs 10 Aug 2007 09:59:51 -0000 1.32 --- CompilerCore.cs 21 Sep 2007 07:58:39 -0000 1.33 *************** *** 99,102 **** --- 99,104 ---- private static readonly Regex LegalWildcardLongFilename = new Regex(String.Concat("^", LegalWildcardLongFilenameCharacters, @"{1,259}$")); + private static readonly Regex PropertySearch = new Regex(@"\[[#$!]?[a-zA-Z_][a-zA-Z0-9_\.]*]", RegexOptions.Singleline); + private TableDefinitionCollection tableDefinitions; private Hashtable extensions; *************** *** 438,441 **** --- 440,453 ---- /// <summary> + /// Checks if the string contains a property (i.e. "foo[Property]bar") + /// </summary> + /// <param name="possibleProperty">String to evaluate for properties.</param> + /// <returns>True if a property is found in the string.</returns> + public static bool ContainsProperty(string possibleProperty) + { + return CompilerCore.PropertySearch.IsMatch(possibleProperty); + } + + /// <summary> /// Get an node's inner text and trims any extra whitespace. /// </summary> Index: Decompiler.cs =================================================================== RCS file: /cvsroot/wix/wix/src/wix/Decompiler.cs,v retrieving revision 1.51 retrieving revision 1.52 diff -C2 -d -r1.51 -r1.52 *** Decompiler.cs 3 Sep 2007 21:53:28 -0000 1.51 --- Decompiler.cs 21 Sep 2007 07:58:39 -0000 1.52 *************** *** 7960,7979 **** { case "Critical Update": ! patchMetadata.Classification = Wix.PatchMetadata.ClassificationType.CriticalUpdate; break; case "Hotfix": ! patchMetadata.Classification = Wix.PatchMetadata.ClassificationType.Hotfix; break; case "Security Rollup": ! patchMetadata.Classification = Wix.PatchMetadata.ClassificationType.SecurityRollup; break; case "Service Pack": ! patchMetadata.Classification = Wix.PatchMetadata.ClassificationType.ServicePack; break; case "Update": ! patchMetadata.Classification = Wix.PatchMetadata.ClassificationType.Update; break; case "Update Rollup": ! patchMetadata.Classification = Wix.PatchMetadata.ClassificationType.UpdateRollup; break; default: --- 7960,7979 ---- { case "Critical Update": ! patchMetadata.Classification = Wix.PatchClassificationType.CriticalUpdate; break; case "Hotfix": ! patchMetadata.Classification = Wix.PatchClassificationType.Hotfix; break; case "Security Rollup": ! patchMetadata.Classification = Wix.PatchClassificationType.SecurityRollup; break; case "Service Pack": ! patchMetadata.Classification = Wix.PatchClassificationType.ServicePack; break; case "Update": ! patchMetadata.Classification = Wix.PatchClassificationType.Update; break; case "Update Rollup": ! patchMetadata.Classification = Wix.PatchClassificationType.UpdateRollup; break; default: *************** *** 8018,8021 **** --- 8018,8041 ---- } break; + case "OptimizeCA": + Wix.OptimizeCustomActions optimizeCustomActions = new Wix.OptimizeCustomActions(); + int optimizeCA = int.Parse(value); + if (0 != ((int)OptimizeCA.SkipAssignment & optimizeCA)) + { + optimizeCustomActions.SkipAssignment = Wix.YesNoType.yes; + } + + if (0 != ((int)OptimizeCA.SkipImmediate & optimizeCA)) + { + optimizeCustomActions.SkipImmediate = Wix.YesNoType.yes; + } + + if (0 != ((int)OptimizeCA.SkipDeferred & optimizeCA)) + { + optimizeCustomActions.SkipDeferred = Wix.YesNoType.yes; + } + + patchMetadata.AddChild(optimizeCustomActions); + break; case "OptimizedInstallMode": if ("1" == value) Index: wix.csproj =================================================================== RCS file: /cvsroot/wix/wix/src/wix/wix.csproj,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -d -r1.32 -r1.33 *** wix.csproj 3 Sep 2007 21:53:29 -0000 1.32 --- wix.csproj 21 Sep 2007 07:58:40 -0000 1.33 *************** *** 137,140 **** --- 137,141 ---- <SubType>Code</SubType> </Compile> + <Compile Include="ComponentRow.cs" /> <Compile Include="Patch.cs" /> <Compile Include="PatchTransform.cs" /> *************** *** 400,403 **** --- 401,409 ---- </EmbeddedResource> </ItemGroup> + <ItemGroup> + <None Include="Xsd\wix.xsx"> + <DependentUpon>wix.xsd</DependentUpon> + </None> + </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <PropertyGroup> *************** *** 409,411 **** </PostBuildEvent> </PropertyGroup> ! </Project> --- 415,417 ---- </PostBuildEvent> </PropertyGroup> ! </Project> \ No newline at end of file --- NEW FILE: ComponentRow.cs --- //------------------------------------------------------------------------------------------------- // <copyright file="ComponentRow.cs" company="Microsoft"> // Copyright (c) Microsoft Corporation. All rights reserved. // </copyright> // // <summary> // Specialization of a row for the Component table. // </summary> //------------------------------------------------------------------------------------------------- namespace Microsoft.Tools.WindowsInstallerXml { using System; using System.Text; using System.Xml; using Microsoft.Tools.WindowsInstallerXml.Msi.Interop; /// <summary> /// Specialization of a row for the Component table. /// </summary> public sealed class ComponentRow : Row { private string sourceFile; /// <summary> /// Creates a Control row that belongs to a table. /// </summary> /// <param name="sourceLineNumbers">Original source lines for this row.</param> /// <param name="table">Table this Component row belongs to and should get its column definitions from.</param> public ComponentRow(SourceLineNumberCollection sourceLineNumbers, Table table) : base(sourceLineNumbers, table) { } /// <summary> /// Gets or sets the identifier for this Component row. /// </summary> /// <value>Identifier for this Component row.</value> public string Component { get { return (string)this.Fields[0].Data; } set { this.Fields[0].Data = value; } } /// <summary> /// Gets or sets the ComponentId for this Component row. /// </summary> /// <value>guid for this Component row.</value> public string Guid { get { return (string)this.Fields[1].Data; } set { this.Fields[1].Data = value; } } /// <summary> /// Gets or sets the Directory_ of the Component. /// </summary> /// <value>Directory of the Component.</value> public string Directory { get { return (string)this.Fields[2].Data; } set { this.Fields[2].Data = value; } } /// <summary> /// Gets or sets the local only attribute of the Component. /// </summary> /// <value>Local only attribute of the component.</value> public bool IsLocalOnly { get { return MsiInterop.MsidbComponentAttributesLocalOnly == ((int)this.Fields[3].Data & MsiInterop.MsidbComponentAttributesLocalOnly); } set { if (value) { this.Fields[3].Data = (int)this.Fields[3].Data | MsiInterop.MsidbComponentAttributesLocalOnly; } else { this.Fields[3].Data = (int)this.Fields[3].Data & ~MsiInterop.MsidbComponentAttributesLocalOnly; } } } /// <summary> /// Gets or sets the source only attribute of the Component. /// </summary> /// <value>Source only attribute of the component.</value> public bool IsSourceOnly { get { return MsiInterop.MsidbComponentAttributesSourceOnly == ((int)this.Fields[3].Data & MsiInterop.MsidbComponentAttributesSourceOnly); } set { if (value) { this.Fields[3].Data = (int)this.Fields[3].Data | MsiInterop.MsidbComponentAttributesSourceOnly; } else { this.Fields[3].Data = (int)this.Fields[3].Data & ~MsiInterop.MsidbComponentAttributesSourceOnly; } } } /// <summary> /// Gets or sets the optional attribute of the Component. /// </summary> /// <value>Optional attribute of the component.</value> public bool IsOptional { get { return MsiInterop.MsidbComponentAttributesOptional == ((int)this.Fields[3].Data & MsiInterop.MsidbComponentAttributesOptional); } set { if (value) { this.Fields[3].Data = (int)this.Fields[3].Data | MsiInterop.MsidbComponentAttributesOptional; } else { this.Fields[3].Data = (int)this.Fields[3].Data & ~MsiInterop.MsidbComponentAttributesOptional; } } } /// <summary> /// Gets or sets the registry key path attribute of the Component. /// </summary> /// <value>Registry key path attribute of the component.</value> public bool IsRegistryKeyPath { get { return MsiInterop.MsidbComponentAttributesRegistryKeyPath == ((int)this.Fields[3].Data & MsiInterop.MsidbComponentAttributesRegistryKeyPath); } set { if (value) { this.Fields[3].Data = (int)this.Fields[3].Data | MsiInterop.MsidbComponentAttributesRegistryKeyPath; } else { this.Fields[3].Data = (int)this.Fields[3].Data & ~MsiInterop.MsidbComponentAttributesRegistryKeyPath; } } } /// <summary> /// Gets or sets the shared dll ref count attribute of the Component. /// </summary> /// <value>Shared dll ref countattribute of the component.</value> public bool IsSharedDll { get { return MsiInterop.MsidbComponentAttributesSharedDllRefCount == ((int)this.Fields[3].Data & MsiInterop.MsidbComponentAttributesSharedDllRefCount); } set { if (value) { this.Fields[3].Data = (int)this.Fields[3].Data | MsiInterop.MsidbComponentAttributesSharedDllRefCount; } else { this.Fields[3].Data = (int)this.Fields[3].Data & ~MsiInterop.MsidbComponentAttributesSharedDllRefCount; } } } /// <summary> /// Gets or sets the permanent attribute of the Component. /// </summary> /// <value>Permanent attribute of the component.</value> public bool IsPermanent { get { return MsiInterop.MsidbComponentAttributesPermanent == ((int)this.Fields[3].Data & MsiInterop.MsidbComponentAttributesPermanent); } set { if (value) { this.Fields[3].Data = (int)this.Fields[3].Data | MsiInterop.MsidbComponentAttributesPermanent; } else { this.Fields[3].Data = (int)this.Fields[3].Data & ~MsiInterop.MsidbComponentAttributesPermanent; } } } /// <summary> /// Gets or sets the ODBC data source key path attribute of the Component. /// </summary> /// <value>ODBC data source key path attribute of the component.</value> public bool IsOdbcDataSourceKeyPath { get { return MsiInterop.MsidbComponentAttributesODBCDataSource == ((int)this.Fields[3].Data & MsiInterop.MsidbComponentAttributesODBCDataSource); } set { if (value) { this.Fields[3].Data = (int)this.Fields[3].Data | MsiInterop.MsidbComponentAttributesODBCDataSource; } else { this.Fields[3].Data = (int)this.Fields[3].Data & ~MsiInterop.MsidbComponentAttributesODBCDataSource; } } } /// <summary> /// Gets or sets the condition of the Component. /// </summary> /// <value>Condition of the Component.</value> public string Condition { get { return (string)this.Fields[4].Data; } set { this.Fields[4].Data = value; } } /// <summary> /// Gets or sets the key path of the Component. /// </summary> /// <value>Key path of the Component.</value> public string KeyPath { get { return (string)this.Fields[5].Data; } set { this.Fields[5].Data = value; } } /// <summary> /// Gets or sets the source location to the file to fill in the Text of the control. /// </summary> /// <value>Source location to the file to fill in the Text of the control.</value> public string SourceFile { get { return this.sourceFile; } set { this.sourceFile = value; } } } } Index: wixdll.build =================================================================== RCS file: /cvsroot/wix/wix/src/wix/wixdll.build,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** wixdll.build 3 Sep 2007 21:53:29 -0000 1.21 --- wixdll.build 21 Sep 2007 07:58:40 -0000 1.22 *************** *** 152,155 **** --- 152,156 ---- <include name="CompilerCore.cs" /> <include name="CompilerExtension.cs" /> + <include name="ComponentRow.cs" /> <include name="ConnectToFeature.cs" /> <include name="ConnectToFeatureCollection.cs" /> Index: Uuid.cs =================================================================== RCS file: /cvsroot/wix/wix/src/wix/Uuid.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Uuid.cs 13 Sep 2006 08:13:36 -0000 1.1 --- Uuid.cs 21 Sep 2007 07:58:40 -0000 1.2 *************** *** 51,58 **** /// <param name="namespaceGuid">The namespace UUID.</param> /// <param name="value">The value.</param> /// <returns>The UUID for the given namespace and value.</returns> ! public static Guid NewUuid(Guid namespaceGuid, string value) { byte[] namespaceBytes = namespaceGuid.ToByteArray(); // get the fields of the guid which are in host byte ordering --- 51,60 ---- /// <param name="namespaceGuid">The namespace UUID.</param> /// <param name="value">The value.</param> + /// <param name="backwardsCompatible">Flag to say to use MD5 instead of better SHA1.</param> /// <returns>The UUID for the given namespace and value.</returns> ! public static Guid NewUuid(Guid namespaceGuid, string value, bool backwardsCompatible) { byte[] namespaceBytes = namespaceGuid.ToByteArray(); + short uuidVersion = backwardsCompatible ? (short)0x3000 : (short)0x5000; // get the fields of the guid which are in host byte ordering *************** *** 69,73 **** byte[] valueBytes = Encoding.Unicode.GetBytes(value); ! // fill-in the MD5 input buffer byte[] buffer = new byte[namespaceBytes.Length + valueBytes.Length]; Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, buffer, 0, 4); --- 71,75 ---- byte[] valueBytes = Encoding.Unicode.GetBytes(value); ! // fill-in the hash input buffer byte[] buffer = new byte[namespaceBytes.Length + valueBytes.Length]; Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, buffer, 0, 4); *************** *** 77,85 **** Buffer.BlockCopy(valueBytes, 0, buffer, 16, valueBytes.Length); ! // perform an MD5 hash of the namespace and value byte[] hash; ! using (MD5 md5 = MD5.Create()) { ! hash = md5.ComputeHash(buffer); } --- 79,97 ---- Buffer.BlockCopy(valueBytes, 0, buffer, 16, valueBytes.Length); ! // perform the appropriate hash of the namespace and value byte[] hash; ! if (backwardsCompatible) { ! using (MD5 md5 = MD5.Create()) ! { ! hash = md5.ComputeHash(buffer); ! } ! } ! else ! { ! using (SHA1 sha1 = SHA1.Create()) ! { ! hash = sha1.ComputeHash(buffer); ! } } *************** *** 96,109 **** // set the version and variant bits timeHiAndVersion &= 0x0FFF; ! timeHiAndVersion += 0x3000; // version 3 hash[8] &= 0x3F; hash[8] |= 0x80; ! // put back the converted values ! Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, hash, 0, 4); ! Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, hash, 4, 2); ! Buffer.BlockCopy(BitConverter.GetBytes(timeHiAndVersion), 0, hash, 6, 2); ! return new Guid(hash); } } --- 108,124 ---- // set the version and variant bits timeHiAndVersion &= 0x0FFF; ! timeHiAndVersion += uuidVersion; hash[8] &= 0x3F; hash[8] |= 0x80; ! // put back the converted values into a 128-bit value ! byte[] guidBits = new byte[16]; ! Buffer.BlockCopy(hash, 0, guidBits, 0, 16); ! Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, guidBits, 0, 4); ! Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, guidBits, 4, 2); ! Buffer.BlockCopy(BitConverter.GetBytes(timeHiAndVersion), 0, guidBits, 6, 2); ! ! return new Guid(guidBits); } } Index: Table.cs =================================================================== RCS file: /cvsroot/wix/wix/src/wix/Table.cs,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** Table.cs 29 Nov 2006 20:55:18 -0000 1.17 --- Table.cs 21 Sep 2007 07:58:40 -0000 1.18 *************** *** 129,132 **** --- 129,135 ---- row = new BBControlRow(sourceLineNumbers, this); break; + case "Component": + row = new ComponentRow(sourceLineNumbers, this); + break; case "Control": row = new ControlRow(sourceLineNumbers, this); Index: Compiler.cs =================================================================== RCS file: /cvsroot/wix/wix/src/wix/Compiler.cs,v retrieving revision 1.66 retrieving revision 1.67 diff -C2 -d -r1.66 -r1.67 *** Compiler.cs 3 Sep 2007 21:53:27 -0000 1.66 --- Compiler.cs 21 Sep 2007 07:58:38 -0000 1.67 *************** *** 1974,1977 **** --- 1974,1978 ---- bool keyFound = false; string keyPath = null; + bool keyPathContainsProperties = false; bool shouldAddCreateFolder = false; bool win64 = false; *************** *** 2125,2128 **** --- 2126,2130 ---- bool keyPathSet = false; string keyPossible = null; + bool containsProperties = false; int keyBit = 0; switch (child.LocalName) *************** *** 2195,2203 **** break; case "RegistryKey": ! keyPathSet = this.ParseRegistryKeyElement(child, id, CompilerCore.IntegerNotSet, null, out keyPossible); keyBit = MsiInterop.MsidbComponentAttributesRegistryKeyPath; break; case "RegistryValue": ! keyPathSet = this.ParseRegistryValueElement(child, id, CompilerCore.IntegerNotSet, null, out keyPossible); keyBit = MsiInterop.MsidbComponentAttributesRegistryKeyPath; break; --- 2197,2205 ---- break; case "RegistryKey": ! keyPathSet = this.ParseRegistryKeyElement(child, id, CompilerCore.IntegerNotSet, null, out keyPossible, out containsProperties); keyBit = MsiInterop.MsidbComponentAttributesRegistryKeyPath; break; case "RegistryValue": ! keyPathSet = this.ParseRegistryValueElement(child, id, CompilerCore.IntegerNotSet, null, out keyPossible, out containsProperties); keyBit = MsiInterop.MsidbComponentAttributesRegistryKeyPath; break; *************** *** 2248,2251 **** --- 2250,2254 ---- keyFound = keyPathSet; keyPath = keyPossible; + keyPathContainsProperties = containsProperties; keyBits = keyBit; } *************** *** 2274,2285 **** { // check for conditions that may exclude this component from using generated guids ! if (1 != files || encounteredODBCDataSource || 0 != keyBits) { this.core.OnMessage(WixErrors.IllegalComponentWithGeneratableGuid(sourceLineNumbers)); } - else // TODO: remove this warning about using this experimental functionality - { - this.core.OnMessage(WixWarnings.GeneratableComponentGuidsAreDangerous(sourceLineNumbers)); - } } --- 2277,2287 ---- { // check for conditions that may exclude this component from using generated guids ! if (encounteredODBCDataSource || ! (1 != files && 0 == keyBits) || ! (0 != files && MsiInterop.MsidbComponentAttributesRegistryKeyPath == keyBits) || ! (0 == files && MsiInterop.MsidbComponentAttributesRegistryKeyPath == keyBits && keyPathContainsProperties)) { this.core.OnMessage(WixErrors.IllegalComponentWithGeneratableGuid(sourceLineNumbers)); } } *************** *** 3768,3771 **** --- 3770,3774 ---- SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string id = null; + string componentGuidGenerationSeed = null; bool fileSourceAttribSet = false; string longName = null; *************** *** 3786,3789 **** --- 3789,3795 ---- id = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; + case "ComponentGuidGenerationSeed": + componentGuidGenerationSeed = this.core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); + break; case "DiskId": diskId = this.core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue); *************** *** 4068,4071 **** --- 4074,4084 ---- row[1] = parentId; row[2] = defaultDir.ToString(); + + if (null != componentGuidGenerationSeed) + { + Row wixRow = this.core.CreateRow(sourceLineNumbers, "WixDirectory"); + wixRow[0] = id; + wixRow[1] = componentGuidGenerationSeed; + } } } *************** *** 8886,8890 **** --- 8899,8907 ---- string displayName = null; string manufacturer = null; + YesNoType minorUpdateTargetRTM = YesNoType.NotSet; string moreInfoUrl = null; + int optimizeCA = CompilerCore.IntegerNotSet; + YesNoType optimizedInstallMode = YesNoType.NotSet; + string targetProductName = null; // string replaceGuids = String.Empty; *************** *** 8940,8946 **** --- 8957,8972 ---- manufacturer = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; + case "MinorUpdateTargetRTM": + minorUpdateTargetRTM = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; case "MoreInfoURL": moreInfoUrl = this.core.GetAttributeValue(sourceLineNumbers, attrib); break; + case "OptimizedInstallMode": + optimizedInstallMode = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "TargetProductName": + targetProductName = this.core.GetAttributeValue(sourceLineNumbers, attrib); + break; default: this.core.UnexpectedAttribute(sourceLineNumbers, attrib); *************** *** 8999,9002 **** --- 9025,9031 ---- this.ParseMediaElement(child, patchId); break; + case "OptimizeCustomActions": + optimizeCA = this.ParseOptimizeCustomActionsElement(child); + break; case "PatchFamily": this.ParsePatchFamilyElement(child); *************** *** 9042,9045 **** --- 9071,9082 ---- } + // always generate the CreationTimeUTC + { + Row row = this.core.CreateRow(sourceLineNumbers, "MsiPatchMetadata"); + row[0] = null; + row[1] = "CreationTimeUTC"; + row[2] = DateTime.UtcNow.ToString("MM-dd-yy HH:mm", CultureInfo.InvariantCulture); + } + if (null != description) { *************** *** 9066,9069 **** --- 9103,9114 ---- } + if (YesNoType.NotSet != minorUpdateTargetRTM) + { + Row row = this.core.CreateRow(sourceLineNumbers, "MsiPatchMetadata"); + row[0] = null; + row[1] = "MinorUpdateTargetRTM"; + row[2] = YesNoType.Yes == minorUpdateTargetRTM ? "1" : "0"; + } + if (null != moreInfoUrl) { *************** *** 9073,9076 **** --- 9118,9145 ---- row[2] = moreInfoUrl; } + + if (CompilerCore.IntegerNotSet != optimizeCA) + { + Row row = this.core.CreateRow(sourceLineNumbers, "MsiPatchMetadata"); + row[0] = null; + row[1] = "OptimizeCA"; + row[2] = optimizeCA.ToString(CultureInfo.InvariantCulture); + } + + if (YesNoType.NotSet != optimizedInstallMode) + { + Row row = this.core.CreateRow(sourceLineNumbers, "MsiPatchMetadata"); + row[0] = null; + row[1] = "OptimizedInstallMode"; + row[2] = YesNoType.Yes == optimizedInstallMode ? "1" : "0"; + } + + if (null != targetProductName) + { + Row row = this.core.CreateRow(sourceLineNumbers, "MsiPatchMetadata"); + row[0] = null; + row[1] = "TargetProductName"; + row[2] = targetProductName; + } } // TODO: do something with versionMismatches and productMismatches *************** *** 10525,10528 **** --- 10594,10598 ---- string minorUpdateTargetRTM = null; string moreInfoUrl = null; + int optimizeCA = CompilerCore.IntegerNotSet; YesNoType optimizedInstallMode = YesNoType.NotSet; string targetProductName = null; *************** *** 10631,10634 **** --- 10701,10707 ---- this.ParseCustomPropertyElement(child); break; + case "OptimizeCustomActions": + optimizeCA = this.ParseOptimizeCustomActionsElement(child); + break; default: this.core.UnexpectedElement(node, child); *************** *** 10709,10712 **** --- 10782,10793 ---- } + if (CompilerCore.IntegerNotSet != optimizeCA) + { + Row row = this.core.CreateRow(sourceLineNumbers, "PatchMetadata"); + row[0] = null; + row[1] = "OptimizeCA"; + row[2] = optimizeCA.ToString(CultureInfo.InvariantCulture); + } + if (YesNoType.NotSet != optimizedInstallMode) { *************** *** 10804,10807 **** --- 10885,10936 ---- /// <summary> + /// Parses the OptimizeCustomActions element. + /// </summary> + /// <param name="node">Element to parse.</param> + /// <returns>The combined integer value for callers to store as appropriate.</returns> + private int ParseOptimizeCustomActionsElement(XmlNode node) + { + SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + OptimizeCA optimizeCA = OptimizeCA.None; + + foreach (XmlAttribute attrib in node.Attributes) + { + if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace) + { + switch (attrib.LocalName) + { + case "SkipAssignment": + if (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + optimizeCA |= OptimizeCA.SkipAssignment; + } + break; + case "SkipImmediate": + if (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + optimizeCA |= OptimizeCA.SkipImmediate; + } + break; + case "SkipDeferred": + if (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + optimizeCA |= OptimizeCA.SkipDeferred; + } + break; + default: + this.core.UnexpectedAttribute(sourceLineNumbers, attrib); + break; + } + } + else + { + this.core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib); + } + } + + return (int)optimizeCA; + } + + /// <summary> /// Parses a patch information element. /// </summary> *************** *** 11733,11738 **** /// <param name="parentKey">Parent key for this Registry element when nested.</param> /// <param name="possibleKeyPath">Identifier of this registry key since it could be the component's keypath.</param> /// <returns>True if registry element is marked as component's keypath</returns> ! private bool ParseRegistryKeyElement(XmlNode node, string componentId, int root, string parentKey, out string possibleKeyPath) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); --- 11862,11868 ---- /// <param name="parentKey">Parent key for this Registry element when nested.</param> /// <param name="possibleKeyPath">Identifier of this registry key since it could be the component's keypath.</param> + /// <param name="containsProperties">Flag specifying that the registry key has at least one embedded Property (i.e. Key="[Property]").</param> /// <returns>True if registry element is marked as component's keypath</returns> ! private bool ParseRegistryKeyElement(XmlNode node, string componentId, int root, string parentKey, out string possibleKeyPath, out bool containsProperties) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); *************** *** 11742,11748 **** string action = null; bool keyPath = false; - bool couldBeKeyPath = true; // assume that this is a regular registry key that could become the key path possibleKeyPath = null; foreach (XmlAttribute attrib in node.Attributes) --- 11872,11878 ---- string action = null; bool keyPath = false; possibleKeyPath = null; + containsProperties = false; foreach (XmlAttribute attrib in node.Attributes) *************** *** 11865,11873 **** { string possibleChildKeyPath = null; switch (child.LocalName) { case "RegistryKey": ! if (this.ParseRegistryKeyElement(child, componentId, root, key, out possibleChildKeyPath)) { if (keyPath) --- 11995,12004 ---- { string possibleChildKeyPath = null; + bool childContainsProperties = false; switch (child.LocalName) { case "RegistryKey": ! if (this.ParseRegistryKeyElement(child, componentId, root, key, out possibleChildKeyPath, out childContainsProperties)) { if (keyPath) *************** *** 11877,11885 **** possibleKeyPath = possibleChildKeyPath; // the child is the key path keyPath = true; } break; case "RegistryValue": ! if (this.ParseRegistryValueElement(child, componentId, root, key, out possibleChildKeyPath)) { if (keyPath) --- 12008,12022 ---- possibleKeyPath = possibleChildKeyPath; // the child is the key path + containsProperties = childContainsProperties; keyPath = true; } + else if (null == possibleKeyPath && null != possibleChildKeyPath) + { + possibleKeyPath = possibleChildKeyPath; + containsProperties = childContainsProperties; + } break; case "RegistryValue": ! if (this.ParseRegistryValueElement(child, componentId, root, key, out possibleChildKeyPath, out childContainsProperties)) { if (keyPath) *************** *** 11889,11894 **** --- 12026,12037 ---- possibleKeyPath = possibleChildKeyPath; // the child is the key path + containsProperties = childContainsProperties; keyPath = true; } + else if (null == possibleKeyPath && null != possibleChildKeyPath) + { + possibleKeyPath = possibleChildKeyPath; + containsProperties = childContainsProperties; + } break; case "Permission": *************** *** 11922,11933 **** } - // If this was just a regular registry key (that could be the key path) - // and no child registry key set the possible key path, let's make this - // Registry/@Id a possible key path. - if (couldBeKeyPath && null == possibleKeyPath) - { - possibleKeyPath = id; - } - return keyPath; } --- 12065,12068 ---- *************** *** 11941,11946 **** /// <param name="parentKey">Root specified when element is nested under a RegistryKey element, otherwise CompilerCore.IntegerNotSet.</param> /// <param name="possibleKeyPath">Identifier of this registry key since it could be the component's keypath.</param> /// <returns>True if registry element is marked as component's keypath</returns> ! private bool ParseRegistryValueElement(XmlNode node, string componentId, int root, string parentKey, out string possibleKeyPath) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); --- 12076,12082 ---- /// <param name="parentKey">Root specified when element is nested under a RegistryKey element, otherwise CompilerCore.IntegerNotSet.</param> /// <param name="possibleKeyPath">Identifier of this registry key since it could be the component's keypath.</param> + /// <param name="containsProperties">Flag specifying that the registry key has at least one embedded Property (i.e. Key="[Property]").</param> /// <returns>True if registry element is marked as component's keypath</returns> ! private bool ParseRegistryValueElement(XmlNode node, string componentId, int root, string parentKey, out string possibleKeyPath, out bool containsProperties) { SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); *************** *** 11955,11958 **** --- 12091,12095 ---- possibleKeyPath = null; + containsProperties = false; foreach (XmlAttribute attrib in node.Attributes) *************** *** 12182,12185 **** --- 12319,12324 ---- row[4] = value; row[5] = componentId; + + containsProperties = CompilerCore.ContainsProperty(String.Concat(key, "\\", name)); } *************** *** 12780,12791 **** --- 12919,12938 ---- case "createKey": name = "+"; + couldBeKeyPath = false; break; case "createKeyAndRemoveKeyOnUninstall": name = "*"; + couldBeKeyPath = false; break; case "removeKeyOnUninstall": name = "-"; + couldBeKeyPath = false; break; } + + if (keyPath) + { + this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "KeyPath", "Action", action)); + } } else // name specified, no value Index: Binder.cs =================================================================== RCS file: /cvsroot/wix/wix/src/wix/Binder.cs,v retrieving revision 1.52 retrieving revision 1.53 diff -C2 -d -r1.52 -r1.53 *** Binder.cs 3 Sep 2007 21:53:27 -0000 1.52 --- Binder.cs 21 Sep 2007 07:58:38 -0000 1.53 *************** *** 64,67 **** --- 64,68 ---- private WixVariableResolver wixVariableResolver; private int cabbingThreadCount; + private bool backwardsCompatibleGuidGen; /// <summary> *************** *** 82,85 **** --- 83,96 ---- /// <summary> + /// Gets or sets whether the GUID generation should use a backwards + /// compatible version (i.e. MD5). + /// </summary> + public bool BackwardsCompatibleGuidGen + { + get { return this.backwardsCompatibleGuidGen; } + set { this.backwardsCompatibleGuidGen = value; } + } + + /// <summary> /// Gets or sets the binder extension class. /// </summary> *************** *** 590,597 **** /// </summary> /// <param name="directories">All cached directories.</param> /// <param name="directory">Directory identifier.</param> /// <param name="canonicalize">Canonicalize the path for standard directories.</param> /// <returns>Source path of a directory.</returns> ! private static string GetDirectoryPath(Hashtable directories, string directory, bool canonicalize) { if (!directories.Contains(directory)) --- 601,609 ---- /// </summary> /// <param name="directories">All cached directories.</param> + /// <param name="componentIdGenSeeds">Hash table of Component GUID generation seeds indexed by directory id.</param> /// <param name="directory">Directory identifier.</param> /// <param name="canonicalize">Canonicalize the path for standard directories.</param> /// <returns>Source path of a directory.</returns> ! private static string GetDirectoryPath(Hashtable directories, Hashtable componentIdGenSeeds, string directory, bool canonicalize) { if (!directories.Contains(directory)) *************** *** 603,607 **** if (null == resolvedDirectory.Path) { ! if (canonicalize && Installer.IsStandardDirectory(directory)) { // when canonicalization is on, standard directories are treated equally --- 615,623 ---- if (null == resolvedDirectory.Path) { ! if (null != componentIdGenSeeds && componentIdGenSeeds.Contains(directory)) ! { ! resolvedDirectory.Path = (string)componentIdGenSeeds[directory]; ! } ! else if (canonicalize && Installer.IsStandardDirectory(directory)) { // when canonicalization is on, standard directories are treated equally *************** *** 623,627 **** else { ! string parentPath = GetDirectoryPath(directories, resolvedDirectory.DirectoryParent, canonicalize); if (null != resolvedDirectory.Name) --- 639,643 ---- else { ! string parentPath = GetDirectoryPath(directories, componentIdGenSeeds, resolvedDirectory.DirectoryParent, canonicalize); if (null != resolvedDirectory.Name) *************** *** 2094,2139 **** private void SetComponentGuids(Output output) { ! Table componentTable = output.Tables["Component"]; ! Table directoryTable = output.Tables["Directory"]; ! Table fileTable = output.Tables["File"]; ! if (null != componentTable && null != directoryTable && null != fileTable) { ... [truncated message content] |