UtilFinalizeHarvesterMutator.cs :  » Installers-Generators » WiX » Microsoft » Tools » WindowsInstallerXml » Extensions » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Installers Generators » WiX 
WiX » Microsoft » Tools » WindowsInstallerXml » Extensions » UtilFinalizeHarvesterMutator.cs
//-------------------------------------------------------------------------------------------------
// <copyright file="UtilFinalizeHarvesterMutator.cs" company="Microsoft">
//    Copyright (c) Microsoft Corporation.  All rights reserved.
//    
//    The use and distribution terms for this software are covered by the
//    Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
//    which can be found in the file CPL.TXT at the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by
//    the terms of this license.
//    
//    You must not remove this notice, or any other, from this software.
// </copyright>
// 
// <summary>
// The finalize harvester mutator for the Windows Installer XML Toolset Utility Extension.
// </summary>
//-------------------------------------------------------------------------------------------------

namespace Microsoft.Tools.WindowsInstallerXml.Extensions{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Text;

    using Wix = Microsoft.Tools.WindowsInstallerXml.Serialize;

    /// <summary>
    /// The finalize harvester mutator for the Windows Installer XML Toolset Utility Extension.
    /// </summary>
    public sealed class UtilFinalizeHarvesterMutator : MutatorExtension
    {
        private ArrayList components;
        private ArrayList directories;
        private SortedList directoryPaths;
        private Hashtable filePaths;
        private ArrayList files;
        private ArrayList registryValues;
        private string preprocessorVariable;
        private bool suppressCOMElements;
        private bool suppressVB6COMElements;

        /// <summary>
        /// Instantiate a new UtilFinalizeHarvesterMutator.
        /// </summary>
        public UtilFinalizeHarvesterMutator()
        {
            this.components = new ArrayList();
            this.directories = new ArrayList();
            this.directoryPaths = new SortedList();
            this.filePaths = new Hashtable();
            this.files = new ArrayList();
            this.registryValues = new ArrayList();
        }

        /// <summary>
        /// Gets or sets the preprocessor variable for substitution.
        /// </summary>
        /// <value>The preprocessor variable for substitution.</value>
        public string PreprocessorVariable
        {
            get { return this.preprocessorVariable; }
            set { this.preprocessorVariable = value; }
        }

        /// <summary>
        /// Gets the sequence of the extension.
        /// </summary>
        /// <value>The sequence of the extension.</value>
        public override int Sequence
        {
            get { return 2000; }
        }

        /// <summary>
        /// Gets or sets the option to suppress COM elements.
        /// </summary>
        /// <value>The option to suppress COM elements.</value>
        public bool SuppressCOMElements
        {
            get { return this.suppressCOMElements; }
            set { this.suppressCOMElements = value; }
        }

        /// <summary>
        /// Gets or sets the option to suppress VB6 COM elements.
        /// </summary>
        /// <value>The option to suppress VB6 COM elements.</value>
        public bool SuppressVB6COMElements
        {
            get { return this.suppressVB6COMElements; }
            set { this.suppressVB6COMElements = value; }
        }

        /// <summary>
        /// Mutate a WiX document.
        /// </summary>
        /// <param name="wix">The Wix document element.</param>
        public override void Mutate(Wix.Wix wix)
        {
            this.components.Clear();
            this.directories.Clear();
            this.directoryPaths.Clear();
            this.filePaths.Clear();
            this.files.Clear();
            this.registryValues.Clear();

            // index elements in this wix document
            this.IndexElement(wix);

            this.MutateDirectories();
            this.MutateFiles();
            this.MutateRegistryValues();

            // must occur after all the registry values have been formatted
            this.MutateComponents();
        }

        /// <summary>
        /// Index an element.
        /// </summary>
        /// <param name="element">The element to index.</param>
        private void IndexElement(Wix.ISchemaElement element)
        {
            if (element is Wix.Component)
            {
                // Component elements only need to be indexed if COM registry values will be strongly typed
                if (!this.suppressCOMElements)
                {
                    this.components.Add(element);
                }
            }
            else if (element is Wix.Directory)
            {
                this.directories.Add(element);
            }
            else if (element is Wix.File)
            {
                this.files.Add(element);
            }
            else if (element is Wix.RegistryValue)
            {
                this.registryValues.Add(element);
            }

            // index the child elements
            if (element is Wix.IParentElement)
            {
                foreach (Wix.ISchemaElement childElement in ((Wix.IParentElement)element).Children)
                {
                    this.IndexElement(childElement);
                }
            }
        }

        /// <summary>
        /// Mutate the components.
        /// </summary>
        [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "These strings won't be round-tripped, and have no security impact.")]
        private void MutateComponents()
        {
            if (suppressVB6COMElements)
            {
                // Search for VB6 specific COM registrations
                foreach (Wix.Component component in this.components)
                {
                    ArrayList vb6RegistryValues = new ArrayList();

                    foreach (Wix.RegistryValue registryValue in component[typeof(Wix.RegistryValue)])
                    {
                        if (Wix.RegistryValue.ActionType.write == registryValue.Action && Wix.RegistryRootType.HKCR == registryValue.Root)
                        {
                            string[] parts = registryValue.Key.Split('\\');

                            if (String.Equals(parts[0], "CLSID", StringComparison.OrdinalIgnoreCase))
                            {
                                // Search for the VB6 CLSID {D5DE8D20-5BB8-11D1-A1E3-00A0C90F2731}
                                if (2 <= parts.Length)
                                {
                                    if (String.Equals(parts[1], "{D5DE8D20-5BB8-11D1-A1E3-00A0C90F2731}", StringComparison.OrdinalIgnoreCase))
                                    {
                                        if (!vb6RegistryValues.Contains(registryValue))
                                        {
                                            vb6RegistryValues.Add(registryValue);
                                        }
                                    }
                                }
                            }
                            else if (String.Equals(parts[0], "TypeLib", StringComparison.OrdinalIgnoreCase))
                            {
                                // Search for the VB6 TypeLibs {EA544A21-C82D-11D1-A3E4-00A0C90AEA82} or {000204EF-0000-0000-C000-000000000046}
                                if (2 <= parts.Length)
                                {
                                    if (String.Equals(parts[1], "{EA544A21-C82D-11D1-A3E4-00A0C90AEA82}", StringComparison.OrdinalIgnoreCase) ||
                                        String.Equals(parts[1], "{000204EF-0000-0000-C000-000000000046}", StringComparison.OrdinalIgnoreCase))
                                    {
                                        if (!vb6RegistryValues.Contains(registryValue))
                                        {
                                            vb6RegistryValues.Add(registryValue);
                                        }
                                    }
                                }
                            }
                            else if (String.Equals(parts[0], "Interface", StringComparison.OrdinalIgnoreCase))
                            {
                                // Search for any Interfaces that reference the VB6 TypeLibs {EA544A21-C82D-11D1-A3E4-00A0C90AEA82} or {000204EF-0000-0000-C000-000000000046}
                                if (3 <= parts.Length)
                                {
                                    if (String.Equals(parts[2], "TypeLib", StringComparison.OrdinalIgnoreCase))
                                    {
                                        if (String.Equals(registryValue.Value, "{EA544A21-C82D-11D1-A3E4-00A0C90AEA82}", StringComparison.OrdinalIgnoreCase) ||
                                            String.Equals(registryValue.Value, "{000204EF-0000-0000-C000-000000000046}", StringComparison.OrdinalIgnoreCase))
                                        {
                                            // Having found a match we have to loop through again finding the matching Interface entries
                                            foreach (Wix.RegistryValue regValue in component[typeof(Wix.RegistryValue)])
                                            {
                                                if (Wix.RegistryValue.ActionType.write == regValue.Action && Wix.RegistryRootType.HKCR == regValue.Root)
                                                {
                                                    string[] rvparts = regValue.Key.Split('\\');
                                                    if (String.Equals(rvparts[0], "Interface", StringComparison.OrdinalIgnoreCase))
                                                    {
                                                        if (2 <= rvparts.Length)
                                                        {
                                                            if (String.Equals(rvparts[1], parts[1], StringComparison.OrdinalIgnoreCase))
                                                            {
                                                                if (!vb6RegistryValues.Contains(regValue))
                                                                {
                                                                    vb6RegistryValues.Add(regValue);
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // Remove all the VB6 specific COM registry values
                    foreach (Object entry in vb6RegistryValues)
                    {
                        component.RemoveChild((Wix.RegistryValue)entry);
                    }
                }
            }

            foreach (Wix.Component component in this.components)
            {
                SortedList indexedElements = CollectionsUtil.CreateCaseInsensitiveSortedList();
                SortedList indexedRegistryValues = CollectionsUtil.CreateCaseInsensitiveSortedList();
                List<Wix.RegistryValue> duplicateRegistryValues = new List<Wix.RegistryValue>();

                // index all the File elements
                foreach (Wix.File file in component[typeof(Wix.File)])
                {
                    indexedElements.Add(String.Concat("file/", file.Id), file);
                }

                // group all the registry values by the COM element they would correspond to and
                // create a COM element for each group
                foreach (Wix.RegistryValue registryValue in component[typeof(Wix.RegistryValue)])
                {
                    if (Wix.RegistryValue.ActionType.write == registryValue.Action && Wix.RegistryRootType.HKCR == registryValue.Root && Wix.RegistryValue.TypeType.@string == registryValue.Type)
                    {
                        string index = null;
                        string[] parts = registryValue.Key.Split('\\');

                        // create a COM element for COM registration and index it
                        if (1 <= parts.Length)
                        {
                            if (String.Equals(parts[0], "AppID", StringComparison.OrdinalIgnoreCase))
                            {
                                // only work with GUID AppIds here
                                if (2 <= parts.Length && parts[1].StartsWith("{", StringComparison.Ordinal) && parts[1].EndsWith("}", StringComparison.Ordinal))
                                {
                                    index = String.Concat(parts[0], '/', parts[1]);

                                    if (!indexedElements.Contains(index))
                                    {
                                        Wix.AppId appId = new Wix.AppId();
                                        appId.Id = parts[1].ToUpper(CultureInfo.InvariantCulture);
                                        indexedElements.Add(index, appId);
                                    }
                                }
                            }
                            else if (String.Equals(parts[0], "CLSID", StringComparison.OrdinalIgnoreCase))
                            {
                                if (2 <= parts.Length)
                                {
                                    index = String.Concat(parts[0], '/', parts[1]);

                                    if (!indexedElements.Contains(index))
                                    {
                                        Wix.Class wixClass = new Wix.Class();
                                        wixClass.Id = parts[1].ToUpper(CultureInfo.InvariantCulture);
                                        indexedElements.Add(index, wixClass);
                                    }
                                }
                            }
                            else if (String.Equals(parts[0], "Component Categories", StringComparison.OrdinalIgnoreCase))
                            {
                                // TODO: add support for this to the compiler
                            }
                            else if (String.Equals(parts[0], "Interface", StringComparison.OrdinalIgnoreCase))
                            {                            
                                if (2 <= parts.Length)
                                {
                                    index = String.Concat(parts[0], '/', parts[1]);

                                    if (!indexedElements.Contains(index))
                                    {
                                        Wix.Interface wixInterface = new Wix.Interface();
                                        wixInterface.Id = parts[1].ToUpper(CultureInfo.InvariantCulture);
                                        indexedElements.Add(index, wixInterface);
                                    }
                                }
                            }
                            else if (String.Equals(parts[0], "TypeLib", StringComparison.Ordinal))
                            {
                                if (3 <= parts.Length)
                                {
                                    // use a special index to ensure progIds are processed before classes
                                    index = String.Concat(".typelib/", parts[1], '/', parts[2]);

                                    if (!indexedElements.Contains(index))
                                    {
                                        Version version = TypeLibraryHarvester.ParseHexVersion(parts[2]);
                                        if (version != null)
                                        {
                                            Wix.TypeLib typeLib = new Wix.TypeLib();
                                            typeLib.Id = parts[1].ToUpper(CultureInfo.InvariantCulture);
                                            typeLib.MajorVersion = version.Major;
                                            typeLib.MinorVersion = version.Minor;
                                            indexedElements.Add(index, typeLib);
                                        }
                                        else // not a valid type library registry value
                                        {
                                            index = null;
                                        }
                                    }
                                }
                            }
                            else if (parts[0].StartsWith(".", StringComparison.Ordinal))
                            {
                                // extension
                            }
                            else // ProgId (hopefully)
                            {
                                // use a special index to ensure progIds are processed before classes
                                index = String.Concat(".progid/", parts[0]);

                                if (!indexedElements.Contains(index))
                                {
                                    Wix.ProgId progId = new Wix.ProgId();
                                    progId.Id = parts[0];
                                    indexedElements.Add(index, progId);
                                }
                            }
                        }

                        // index the RegistryValue element according to the COM element it corresponds to
                        if (null != index)
                        {
                            SortedList registryValues = (SortedList)indexedRegistryValues[index];

                            if (null == registryValues)
                            {
                                registryValues = CollectionsUtil.CreateCaseInsensitiveSortedList();
                                indexedRegistryValues.Add(index, registryValues);
                            }

                            try
                            {
                                registryValues.Add(String.Concat(registryValue.Key, '/', registryValue.Name), registryValue);
                            }
                            catch (ArgumentException)
                            {
                                duplicateRegistryValues.Add(registryValue);

                                if (String.IsNullOrEmpty(registryValue.Value))
                                {
                                    this.Core.OnMessage(UtilWarnings.DuplicateDllRegistryEntry(String.Concat(registryValue.Key, '/', registryValue.Name), component.Id));
                                }
                                else
                                {
                                    this.Core.OnMessage(UtilWarnings.DuplicateDllRegistryEntry(String.Concat(registryValue.Key, '/', registryValue.Name), registryValue.Value, component.Id));
                                }
                            }
                        }
                    }
                }

                foreach (Wix.RegistryValue removeRegistryEntry in duplicateRegistryValues)
                {
                    component.RemoveChild(removeRegistryEntry);
                }

                // set various values on the COM elements from their corresponding registry values
                Hashtable indexedProcessedRegistryValues = new Hashtable();
                foreach (DictionaryEntry entry in indexedRegistryValues)
                {
                    Wix.ISchemaElement element = (Wix.ISchemaElement)indexedElements[entry.Key];
                    string parentIndex = null;
                    SortedList registryValues = (SortedList)entry.Value;

                    // element-specific variables (for really tough situations)
                    string classAppId = null;
                    bool threadingModelSet = false;

                    foreach (Wix.RegistryValue registryValue in registryValues.Values)
                    {
                        string[] parts = registryValue.Key.ToLower(CultureInfo.InvariantCulture).Split('\\');
                        bool processed = false;

                        if (element is Wix.AppId)
                        {
                            Wix.AppId appId = (Wix.AppId)element;

                            if (2 == parts.Length)
                            {
                                if (null == registryValue.Name)
                                {
                                    appId.Description = registryValue.Value;
                                    processed = true;
                                }
                            }
                        }
                        else if (element is Wix.Class)
                        {
                            Wix.Class wixClass = (Wix.Class)element;

                            if (2 == parts.Length)
                            {
                                if (null == registryValue.Name)
                                {
                                    wixClass.Description = registryValue.Value;
                                    processed = true;
                                }
                                else if (String.Equals(registryValue.Name, "AppID", StringComparison.OrdinalIgnoreCase))
                                {
                                    classAppId = registryValue.Value;
                                    processed = true;
                                }
                            }
                            else if (3 == parts.Length)
                            {
                                Wix.Class.ContextType contextType = Wix.Class.ContextType.None;

                                switch (parts[2])
                                {
                                    case "control":
                                        wixClass.Control = Wix.YesNoType.yes;
                                        processed = true;
                                        break;
                                    case "inprochandler":
                                        if (null == registryValue.Name)
                                        {
                                            if (null == wixClass.Handler)
                                            {
                                                wixClass.Handler = "1";
                                                processed = true;
                                            }
                                            else if ("2" == wixClass.Handler)
                                            {
                                                wixClass.Handler = "3";
                                                processed = true;
                                            }
                                        }
                                        break;
                                    case "inprochandler32":
                                        if (null == registryValue.Name)
                                        {
                                            if (null == wixClass.Handler)
                                            {
                                                wixClass.Handler = "2";
                                                processed = true;
                                            }
                                            else if ("1" == wixClass.Handler)
                                            {
                                                wixClass.Handler = "3";
                                                processed = true;
                                            }
                                        }
                                        break;
                                    case "inprocserver":
                                        contextType = Wix.Class.ContextType.InprocServer;
                                        break;
                                    case "inprocserver32":
                                        contextType = Wix.Class.ContextType.InprocServer32;
                                        break;
                                    case "insertable":
                                        wixClass.Insertable = Wix.YesNoType.yes;
                                        processed = true;
                                        break;
                                    case "localserver":
                                        contextType = Wix.Class.ContextType.LocalServer;
                                        break;
                                    case "localserver32":
                                        contextType = Wix.Class.ContextType.LocalServer32;
                                        break;
                                    case "progid":
                                        if (null == registryValue.Name)
                                        {
                                            Wix.ProgId progId = (Wix.ProgId)indexedElements[String.Concat(".progid/", registryValue.Value)];

                                            // verify that the versioned ProgId appears under this Class element
                                            // if not, toss the entire element
                                            if (null == progId || wixClass != progId.ParentElement)
                                            {
                                                element = null;
                                            }
                                            else
                                            {
                                                processed = true;
                                            }
                                        }
                                        break;
                                    case "programmable":
                                        wixClass.Programmable = Wix.YesNoType.yes;
                                        processed = true;
                                        break;
                                    case "typelib":
                                        if (null == registryValue.Name)
                                        {
                                            foreach (DictionaryEntry indexedEntry in indexedElements)
                                            {
                                                string key = (string)indexedEntry.Key;
                                                Wix.ISchemaElement possibleTypeLib = (Wix.ISchemaElement)indexedEntry.Value;

                                                if (key.StartsWith(".typelib/", StringComparison.Ordinal) &&
                                                    0 == String.Compare(key, 9, registryValue.Value, 0, registryValue.Value.Length, StringComparison.OrdinalIgnoreCase))
                                                {
                                                    // ensure the TypeLib is nested under the same thing we want the Class under
                                                    if (null == parentIndex || indexedElements[parentIndex] == possibleTypeLib.ParentElement)
                                                    {
                                                        parentIndex = key;
                                                        processed = true;
                                                    }
                                                }
                                            }
                                        }
                                        break;
                                    case "version":
                                        if (null == registryValue.Name)
                                        {
                                            wixClass.Version = registryValue.Value;
                                            processed = true;
                                        }
                                        break;
                                    case "versionindependentprogid":
                                        if (null == registryValue.Name)
                                        {
                                            Wix.ProgId progId = (Wix.ProgId)indexedElements[String.Concat(".progid/", registryValue.Value)];

                                            // verify that the version independent ProgId appears somewhere
                                            // under this Class element - if not, toss the entire element
                                            if (null == progId || wixClass != progId.ParentElement)
                                            {
                                                // check the parent of the parent
                                                if (null == progId || null == progId.ParentElement || wixClass != progId.ParentElement.ParentElement)
                                                {
                                                    element = null;
                                                }
                                            }

                                            processed = true;
                                        }
                                        break;
                                }

                                if (Wix.Class.ContextType.None != contextType)
                                {
                                    wixClass.Context |= contextType;

                                    if (null == registryValue.Name)
                                    {
                                        if ((registryValue.Value.StartsWith("[!", StringComparison.Ordinal) || registryValue.Value.StartsWith("[#", StringComparison.Ordinal))
                                            && registryValue.Value.EndsWith("]", StringComparison.Ordinal))
                                        {
                                            parentIndex = String.Concat("file/", registryValue.Value.Substring(2, registryValue.Value.Length - 3));
                                            processed = true;
                                        }
                                        else if (registryValue.Value.EndsWith("mscoree.dll", StringComparison.OrdinalIgnoreCase))
                                        {
                                            wixClass.ForeignServer = "mscoree.dll";
                                            processed = true;
                                        }
                                        else if (registryValue.Value.EndsWith("msvbvm60.dll", StringComparison.OrdinalIgnoreCase))
                                        {
                                            wixClass.ForeignServer = "msvbvm60.dll";
                                            processed = true;
                                        }
                                    }
                                    else if (String.Equals(registryValue.Name, "ThreadingModel", StringComparison.OrdinalIgnoreCase))
                                    {
                                        Wix.Class.ThreadingModelType threadingModel;

                                        if (String.Equals(registryValue.Value, "apartment", StringComparison.OrdinalIgnoreCase))
                                        {
                                            threadingModel = Wix.Class.ThreadingModelType.apartment;
                                            processed = true;
                                        }
                                        else if (String.Equals(registryValue.Value, "both", StringComparison.OrdinalIgnoreCase))
                                        {
                                            threadingModel = Wix.Class.ThreadingModelType.both;
                                            processed = true;
                                        }
                                        else if (String.Equals(registryValue.Value, "free", StringComparison.OrdinalIgnoreCase))
                                        {
                                            threadingModel = Wix.Class.ThreadingModelType.free;
                                            processed = true;
                                        }
                                        else if (String.Equals(registryValue.Value, "neutral", StringComparison.OrdinalIgnoreCase))
                                        {
                                            threadingModel = Wix.Class.ThreadingModelType.neutral;
                                            processed = true;
                                        }
                                        else if (String.Equals(registryValue.Value, "rental", StringComparison.OrdinalIgnoreCase))
                                        {
                                            threadingModel = Wix.Class.ThreadingModelType.rental;
                                            processed = true;
                                        }
                                        else if (String.Equals(registryValue.Value, "single", StringComparison.OrdinalIgnoreCase))
                                        {
                                            threadingModel = Wix.Class.ThreadingModelType.single;
                                            processed = true;
                                        }
                                        else
                                        {
                                            continue;
                                        }

                                        if (!threadingModelSet || wixClass.ThreadingModel == threadingModel)
                                        {
                                            wixClass.ThreadingModel = threadingModel;
                                            threadingModelSet = true;
                                        }
                                        else
                                        {
                                            element = null;
                                            break;
                                        }
                                    }
                                }
                            }
                            else if (4 == parts.Length)
                            {
                                if (String.Equals(parts[2], "implemented categories", StringComparison.Ordinal))
                                {
                                    switch (parts[3])
                                    {
                                        case "{7dd95801-9882-11cf-9fa9-00aa006c42c4}":
                                            wixClass.SafeForScripting = Wix.YesNoType.yes;
                                            processed = true;
                                            break;
                                        case "{7dd95802-9882-11cf-9fa9-00aa006c42c4}":
                                            wixClass.SafeForInitializing = Wix.YesNoType.yes;
                                            processed = true;
                                            break;
                                    }
                                }
                            }
                        }
                        else if (element is Wix.Interface)
                        {
                            Wix.Interface wixInterface = (Wix.Interface)element;

                            if (2 == parts.Length && null == registryValue.Name)
                            {
                                wixInterface.Name = registryValue.Value;
                                processed = true;
                            }
                            else if (3 == parts.Length)
                            {
                                switch (parts[2])
                                {
                                    case "proxystubclsid":
                                        if (null == registryValue.Name)
                                        {
                                            wixInterface.ProxyStubClassId = registryValue.Value.ToUpper(CultureInfo.InvariantCulture);
                                            processed = true;
                                        }
                                        break;
                                    case "proxystubclsid32":
                                        if (null == registryValue.Name)
                                        {
                                            wixInterface.ProxyStubClassId32 = registryValue.Value.ToUpper(CultureInfo.InvariantCulture);
                                            processed = true;
                                        }
                                        break;
                                    case "nummethods":
                                        if (null == registryValue.Name)
                                        {
                                            wixInterface.NumMethods = Convert.ToInt32(registryValue.Value, CultureInfo.InvariantCulture);
                                            processed = true;
                                        }
                                        break;
                                    case "typelib":
                                        if (String.Equals("Version", registryValue.Name, StringComparison.OrdinalIgnoreCase))
                                        {
                                            parentIndex = String.Concat(parentIndex, registryValue.Value);
                                            processed = true;
                                        }
                                        else if (null == registryValue.Name) // TypeLib guid
                                        {
                                            parentIndex = String.Concat(".typelib/", registryValue.Value, '/', parentIndex);
                                            processed = true;
                                        }
                                        break;
                                }
                            }
                        }
                        else if (element is Wix.ProgId)
                        {
                            Wix.ProgId progId = (Wix.ProgId)element;

                            if (null == registryValue.Name)
                            {
                                if (1 == parts.Length)
                                {
                                    progId.Description = registryValue.Value;
                                    processed = true;
                                }
                                else if (2 == parts.Length)
                                {
                                    if (String.Equals(parts[1], "CLSID", StringComparison.OrdinalIgnoreCase))
                                    {
                                        parentIndex = String.Concat("CLSID/", registryValue.Value);
                                        processed = true;
                                    }
                                    else if (String.Equals(parts[1], "CurVer", StringComparison.OrdinalIgnoreCase))
                                    {
                                        // this registry value should usually be processed second so the
                                        // version independent ProgId should be under the versioned one
                                        parentIndex = String.Concat(".progid/", registryValue.Value);
                                        processed = true;
                                    }
                                }
                            }
                        }
                        else if (element is Wix.TypeLib)
                        {
                            Wix.TypeLib typeLib = (Wix.TypeLib)element;

                            if (null == registryValue.Name)
                            {
                                if (3 == parts.Length)
                                {
                                    typeLib.Description = registryValue.Value;
                                    processed = true;
                                }
                                else if (4 == parts.Length)
                                {
                                    if (String.Equals(parts[3], "flags", StringComparison.OrdinalIgnoreCase))
                                    {
                                        int flags = Convert.ToInt32(registryValue.Value, CultureInfo.InvariantCulture);

                                        if (0x1 == (flags & 0x1))
                                        {
                                            typeLib.Restricted = Wix.YesNoType.yes;
                                        }

                                        if (0x2 == (flags & 0x2))
                                        {
                                            typeLib.Control = Wix.YesNoType.yes;
                                        }

                                        if (0x4 == (flags & 0x4))
                                        {
                                            typeLib.Hidden = Wix.YesNoType.yes;
                                        }

                                        if (0x8 == (flags & 0x8))
                                        {
                                            typeLib.HasDiskImage = Wix.YesNoType.yes;
                                        }

                                        processed = true;
                                    }
                                    else if (String.Equals(parts[3], "helpdir", StringComparison.OrdinalIgnoreCase))
                                    {
                                        if (registryValue.Value.StartsWith("[", StringComparison.Ordinal) && (registryValue.Value.EndsWith("]", StringComparison.Ordinal)
                                            || registryValue.Value.EndsWith("]\\", StringComparison.Ordinal)))
                                        {
                                            typeLib.HelpDirectory = registryValue.Value.Substring(1, registryValue.Value.LastIndexOf(']') - 1);
                                        }
                                        else if (0 == String.Compare(registryValue.Value, Environment.SystemDirectory, StringComparison.OrdinalIgnoreCase)) // VB6 DLLs register their help directory as SystemFolder
                                        {
                                            typeLib.HelpDirectory = "SystemFolder";
                                        }
                                        else if (null != component.Directory) // -sfrag has not been specified
                                        {
                                            typeLib.HelpDirectory = component.Directory;
                                        }
                                        else if (component.ParentElement is Wix.Directory) // -sfrag has been specified
                                        {
                                            typeLib.HelpDirectory = ((Wix.Directory)component.ParentElement).Id;
                                        }
                                        else if (component.ParentElement is Wix.DirectoryRef) // -sfrag has been specified
                                        {
                                            typeLib.HelpDirectory = ((Wix.DirectoryRef)component.ParentElement).Id;
                                        }

                                        //If the helpdir has not matched a known directory, drop it because it cannot be resolved.
                                        processed = true;
                                    }
                                }
                                else if (5 == parts.Length && String.Equals("win32", parts[4], StringComparison.OrdinalIgnoreCase))
                                {
                                    typeLib.Language = Convert.ToInt32(parts[3], CultureInfo.InvariantCulture);

                                    if ((registryValue.Value.StartsWith("[!", StringComparison.Ordinal) || registryValue.Value.StartsWith("[#", StringComparison.Ordinal))
                                        && registryValue.Value.EndsWith("]", StringComparison.Ordinal))
                                    {
                                        parentIndex = String.Concat("file/", registryValue.Value.Substring(2, registryValue.Value.Length - 3));
                                    }

                                    processed = true;
                                }
                            }
                        }

                        // index the processed registry values by their corresponding COM element
                        if (processed)
                        {
                            indexedProcessedRegistryValues.Add(registryValue, element);
                        }
                    }

                    // parent the COM element
                    if (null != element)
                    {
                        if (null != parentIndex)
                        {
                            Wix.IParentElement parentElement = (Wix.IParentElement)indexedElements[parentIndex];

                            if (null != parentElement)
                            {
                                parentElement.AddChild(element);
                            }
                        }
                        else if(0 < indexedProcessedRegistryValues.Count)
                        {
                            component.AddChild(element);
                        }

                        // special handling for AppID since it doesn't fit the general model
                        if (null != classAppId)
                        {
                            Wix.AppId appId = (Wix.AppId)indexedElements[String.Concat("AppID/", classAppId)];

                            // move the Class element under the AppId (and put the AppId under its old parent)
                            if (null != appId)
                            {
                                // move the AppId element
                                ((Wix.IParentElement)appId.ParentElement).RemoveChild(appId);
                                ((Wix.IParentElement)element.ParentElement).AddChild(appId);

                                // move the Class element
                                ((Wix.IParentElement)element.ParentElement).RemoveChild(element);
                                appId.AddChild(element);
                            }
                        }
                    }
                }

                // remove the RegistryValue elements which were converted into COM elements
                // that were successfully nested under the Component element
                foreach (DictionaryEntry entry in indexedProcessedRegistryValues)
                {
                    Wix.ISchemaElement element = (Wix.ISchemaElement)entry.Value;
                    Wix.RegistryValue registryValue = (Wix.RegistryValue)entry.Key;

                    while (null != element)
                    {
                        if (element == component)
                        {
                            ((Wix.IParentElement)registryValue.ParentElement).RemoveChild(registryValue);
                            break;
                        }

                        element = element.ParentElement;
                    }
                }
            }
        }

        /// <summary>
        /// Mutate the directories.
        /// </summary>
        [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "These strings won't be round-tripped, and have no security impact.")]
        private void MutateDirectories()
        {
            foreach (Wix.Directory directory in this.directories)
            {
                string path = directory.FileSource;

                // create a new directory element without the FileSource attribute
                if (null != path)
                {
                    Wix.Directory newDirectory = new Wix.Directory();

                    newDirectory.Id = directory.Id;
                    newDirectory.Name = directory.Name;

                    foreach (Wix.ISchemaElement element in directory.Children)
                    {
                        newDirectory.AddChild(element);
                    }

                    ((Wix.IParentElement)directory.ParentElement).AddChild(newDirectory);
                    ((Wix.IParentElement)directory.ParentElement).RemoveChild(directory);

                    if (null != newDirectory.Id)
                    {
                        this.directoryPaths[path.ToLower(CultureInfo.InvariantCulture)] = String.Concat("[", newDirectory.Id, "]");
                    }
                }
            }
        }

        /// <summary>
        /// Mutate the files.
        /// </summary>
        [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "These strings won't be round-tripped, and have no security impact.")]
        private void MutateFiles()
        {
            foreach (Wix.File file in this.files)
            {
                if (null != file.Id && null != file.Source)
                {
                    string fileSource = this.Core.ResolveFilePath(file.Source);

                    // index the long path
                    this.filePaths[fileSource.ToLower(CultureInfo.InvariantCulture)] = String.Concat("[#", file.Id, "]");

                    // index the long path as a URL for assembly harvesting
                    Uri fileUri = new Uri(fileSource);
                    this.filePaths[fileUri.ToString().ToLower(CultureInfo.InvariantCulture)] = String.Concat("file:///[#", file.Id, "]");

                    // index the short path
                    string shortPath = NativeMethods.GetShortPathName(fileSource);
                    this.filePaths[shortPath.ToLower(CultureInfo.InvariantCulture)] = String.Concat("[!", file.Id, "]");

                    if (null != this.preprocessorVariable && file.Source.StartsWith("SourceDir\\", StringComparison.Ordinal))
                    {
                        file.Source = file.Source.Substring(9).Insert(0, String.Concat("$(", this.preprocessorVariable, ")"));
                    }
                }
            }
        }

        /// <summary>
        /// Mutate an individual registry string, according to a collection of replacement items.
        /// </summary>
        /// <param name="value">The string to mutate.</param>
        /// <param name="replace">The collection of items to replace within the string.</param>
        /// <value>The mutated registry string.</value>
        [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "These strings won't be round-tripped, and have no security impact.")]
        private string MutateRegistryString(string value, ICollection replace)
        {
            int index;
            string lowercaseValue = value.ToLower(CultureInfo.InvariantCulture);

            foreach (DictionaryEntry entry in replace)
            {
                while (0 <= (index = lowercaseValue.IndexOf((string)entry.Key, StringComparison.Ordinal)))
                {
                    value = value.Remove(index, ((string)entry.Key).Length);
                    value = value.Insert(index, (string)entry.Value);
                    lowercaseValue = value.ToLower(CultureInfo.InvariantCulture);
                }
            }

            return value;
        }

        /// <summary>
        /// Mutate the registry values.
        /// </summary>
        private void MutateRegistryValues()
        {
            ArrayList reversedDirectoryPaths = new ArrayList();

            // reverse the indexed directory paths to ensure the longest paths are found first
            foreach (DictionaryEntry entry in this.directoryPaths)
            {
                reversedDirectoryPaths.Insert(0, entry);
            }

            foreach (Wix.RegistryValue registryValue in this.registryValues)
            {
                // Multi-string values are stored as children - their "Value" member is null
                if (Wix.RegistryValue.TypeType.multiString == registryValue.Type)
                {
                    foreach (Wix.MultiStringValue multiStringValue in registryValue.Children)
                    {
                        // first replace file paths with their MSI tokens
                        multiStringValue.Content = MutateRegistryString(multiStringValue.Content, (ICollection)this.filePaths);
                        // next replace directory paths with their MSI tokens
                        multiStringValue.Content = MutateRegistryString(multiStringValue.Content, (ICollection)reversedDirectoryPaths);
                    }
                }
                else
                {
                    // first replace file paths with their MSI tokens
                    registryValue.Value = MutateRegistryString(registryValue.Value, (ICollection)this.filePaths);
                    // next replace directory paths with their MSI tokens
                    registryValue.Value = MutateRegistryString(registryValue.Value, (ICollection)reversedDirectoryPaths);
                }
            }
        }

        /// <summary>
        /// The native methods for grabbing machine-specific short file paths.
        /// </summary>
        private class NativeMethods
        {
            private const int MaxPath = 255;

            /// <summary>
            /// Gets the short name for a file.
            /// </summary>
            /// <param name="fullPath">Fullpath to file on disk.</param>
            /// <returns>Short name for file.</returns>
            internal static string GetShortPathName(string fullPath)
            {
                StringBuilder shortPath = new StringBuilder(MaxPath, MaxPath);

                uint result = GetShortPathName(fullPath, shortPath, MaxPath);

                if (0 == result)
                {
                    int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                    throw new System.Runtime.InteropServices.COMException("Failed to get short path name", err);
                }

                return shortPath.ToString();
            }

            /// <summary>
            /// Gets the short name for a file.
            /// </summary>
            /// <param name="longPath">Long path to convert to short path.</param>
            /// <param name="shortPath">Short path from long path.</param>
            /// <param name="buffer">Size of short path.</param>
            /// <returns>zero if success.</returns>
            [DllImport("kernel32.dll", EntryPoint = "GetShortPathNameW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
            internal static extern uint GetShortPathName(string longPath, StringBuilder shortPath, [MarshalAs(UnmanagedType.U4)]int buffer);
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.