summaryrefslogtreecommitdiff
path: root/src/tools/heat/UtilHarvesterMutator.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2022-07-26 17:20:39 -0700
committerRob Mensching <rob@firegiant.com>2022-08-01 20:25:19 -0700
commita627ca9b720047e633a8fe72003ab9bee31006c5 (patch)
tree2bc8a924bb4141ab718e74d08f6459a0ffe8d573 /src/tools/heat/UtilHarvesterMutator.cs
parent521eb3c9cf38823a2c4019abb85dc0b3200b92cb (diff)
downloadwix-a627ca9b720047e633a8fe72003ab9bee31006c5.tar.gz
wix-a627ca9b720047e633a8fe72003ab9bee31006c5.tar.bz2
wix-a627ca9b720047e633a8fe72003ab9bee31006c5.zip
Create WixToolset.Heat.nupkg to distribute heat.exe and Heat targets
Moves Heat functionality to the "tools" layer and packages it all up in WixToolset.Heat.nupkg for distribution in WiX v4. Completes 6838
Diffstat (limited to 'src/tools/heat/UtilHarvesterMutator.cs')
-rw-r--r--src/tools/heat/UtilHarvesterMutator.cs218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/tools/heat/UtilHarvesterMutator.cs b/src/tools/heat/UtilHarvesterMutator.cs
new file mode 100644
index 00000000..af2584e3
--- /dev/null
+++ b/src/tools/heat/UtilHarvesterMutator.cs
@@ -0,0 +1,218 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Harvesters
4{
5 using System;
6 using System.Collections;
7 using System.IO;
8 using System.Reflection;
9 using System.Runtime.InteropServices;
10 using WixToolset.Data;
11 using WixToolset.Harvesters.Data;
12 using WixToolset.Harvesters.Extensibility;
13 using Wix = WixToolset.Harvesters.Serialize;
14
15 /// <summary>
16 /// The WiX Toolset harvester mutator.
17 /// </summary>
18 public sealed class UtilHarvesterMutator : BaseMutatorExtension
19 {
20 // Flags for SetErrorMode() native method.
21 private const UInt32 SEM_FAILCRITICALERRORS = 0x0001;
22 private const UInt32 SEM_NOGPFAULTERRORBOX = 0x0002;
23 private const UInt32 SEM_NOALIGNMENTFAULTEXCEPT = 0x0004;
24 private const UInt32 SEM_NOOPENFILEERRORBOX = 0x8000;
25
26 // Remember whether we were able to call OaEnablePerUserTLibRegistration
27 private bool calledPerUserTLibReg;
28
29 /// <summary>
30 /// allow process to handle serious system errors.
31 /// </summary>
32 [DllImport("Kernel32.dll")]
33 private static extern void SetErrorMode(UInt32 uiMode);
34
35 /// <summary>
36 /// enable the RegisterTypeLib API to use the appropriate override mapping for non-admin users on Vista
37 /// </summary>
38 [DllImport("Oleaut32.dll")]
39 private static extern void OaEnablePerUserTLibRegistration();
40
41 public UtilHarvesterMutator()
42 {
43 this.calledPerUserTLibReg = false;
44
45 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
46
47 try
48 {
49 OaEnablePerUserTLibRegistration();
50 this.calledPerUserTLibReg = true;
51 }
52 catch (EntryPointNotFoundException)
53 {
54 }
55 }
56
57 /// <summary>
58 /// Gets the sequence of this mutator extension.
59 /// </summary>
60 /// <value>The sequence of this mutator extension.</value>
61 public override int Sequence
62 {
63 get { return 100; }
64 }
65
66 /// <summary>
67 /// Mutate a WiX document.
68 /// </summary>
69 /// <param name="wix">The Wix document element.</param>
70 public override void Mutate(Wix.Wix wix)
71 {
72 this.MutateElement(null, wix);
73 }
74
75 /// <summary>
76 /// Mutate an element.
77 /// </summary>
78 /// <param name="parentElement">The parent of the element to mutate.</param>
79 /// <param name="element">The element to mutate.</param>
80 private void MutateElement(Wix.IParentElement parentElement, Wix.ISchemaElement element)
81 {
82 if (element is Wix.File)
83 {
84 this.MutateFile(parentElement, (Wix.File)element);
85 }
86
87 // mutate the child elements
88 if (element is Wix.IParentElement)
89 {
90 ArrayList childElements = new ArrayList();
91
92 // copy the child elements to a temporary array (to allow them to be deleted/moved)
93 foreach (Wix.ISchemaElement childElement in ((Wix.IParentElement)element).Children)
94 {
95 childElements.Add(childElement);
96 }
97
98 foreach (Wix.ISchemaElement childElement in childElements)
99 {
100 this.MutateElement((Wix.IParentElement)element, childElement);
101 }
102 }
103 }
104
105 /// <summary>
106 /// Mutate a file.
107 /// </summary>
108 /// <param name="parentElement">The parent of the element to mutate.</param>
109 /// <param name="file">The file to mutate.</param>
110 private void MutateFile(Wix.IParentElement parentElement, Wix.File file)
111 {
112 if (null != file.Source)
113 {
114 string fileExtension = Path.GetExtension(file.Source);
115 string fileSource = this.Core.ResolveFilePath(file.Source);
116
117 if (String.Equals(".ax", fileExtension, StringComparison.OrdinalIgnoreCase) || // DirectShow filter
118 String.Equals(".dll", fileExtension, StringComparison.OrdinalIgnoreCase) ||
119 String.Equals(".exe", fileExtension, StringComparison.OrdinalIgnoreCase) ||
120 String.Equals(".ocx", fileExtension, StringComparison.OrdinalIgnoreCase)) // ActiveX
121 {
122 // try the assembly harvester
123 try
124 {
125 AssemblyHarvester assemblyHarvester = new AssemblyHarvester();
126
127 this.Core.Messaging.Write(HarvesterVerboses.HarvestingAssembly(fileSource));
128 Wix.RegistryValue[] registryValues = assemblyHarvester.HarvestRegistryValues(fileSource);
129
130 foreach (Wix.RegistryValue registryValue in registryValues)
131 {
132 parentElement.AddChild(registryValue);
133 }
134
135 // also try self-reg since we could have a mixed-mode assembly
136 this.HarvestSelfReg(parentElement, fileSource);
137 }
138 catch (BadImageFormatException) // not an assembly, try raw DLL.
139 {
140 this.HarvestSelfReg(parentElement, fileSource);
141 }
142 catch (Exception ex)
143 {
144 this.Core.Messaging.Write(HarvesterWarnings.AssemblyHarvestFailed(fileSource, ex.Message));
145 }
146 }
147 else if (String.Equals(".olb", fileExtension, StringComparison.OrdinalIgnoreCase) || // type library
148 String.Equals(".tlb", fileExtension, StringComparison.OrdinalIgnoreCase)) // type library
149 {
150 // try the type library harvester
151 try
152 {
153 TypeLibraryHarvester typeLibHarvester = new TypeLibraryHarvester();
154
155 this.Core.Messaging.Write(HarvesterVerboses.HarvestingTypeLib(fileSource));
156 Wix.RegistryValue[] registryValues = typeLibHarvester.HarvestRegistryValues(fileSource);
157
158 foreach (Wix.RegistryValue registryValue in registryValues)
159 {
160 parentElement.AddChild(registryValue);
161 }
162 }
163 catch (COMException ce)
164 {
165 // 0x8002801C (TYPE_E_REGISTRYACCESS)
166 // If we don't have permission to harvest typelibs, it's likely because we're on
167 // Vista or higher and aren't an Admin, or don't have the appropriate QFE installed.
168 if (!this.calledPerUserTLibReg && (0x8002801c == unchecked((uint)ce.ErrorCode)))
169 {
170 this.Core.Messaging.Write(WarningMessages.InsufficientPermissionHarvestTypeLib());
171 }
172 else if (0x80029C4A == unchecked((uint)ce.ErrorCode)) // generic can't load type library
173 {
174 this.Core.Messaging.Write(HarvesterWarnings.TypeLibLoadFailed(fileSource, ce.Message));
175 }
176 }
177 }
178 }
179 }
180
181 /// <summary>
182 /// Calls self-reg harvester.
183 /// </summary>
184 /// <param name="parentElement">The parent element.</param>
185 /// <param name="fileSource">The file source.</param>
186 private void HarvestSelfReg(Wix.IParentElement parentElement, string fileSource)
187 {
188 // try the self-reg harvester
189 try
190 {
191 DllHarvester dllHarvester = new DllHarvester();
192
193 this.Core.Messaging.Write(HarvesterVerboses.HarvestingSelfReg(fileSource));
194 Wix.RegistryValue[] registryValues = dllHarvester.HarvestRegistryValues(fileSource);
195
196 foreach (Wix.RegistryValue registryValue in registryValues)
197 {
198 parentElement.AddChild(registryValue);
199 }
200 }
201 catch (TargetInvocationException tie)
202 {
203 if (tie.InnerException is EntryPointNotFoundException)
204 {
205 // No DllRegisterServer(), which is fine by me.
206 }
207 else
208 {
209 this.Core.Messaging.Write(HarvesterWarnings.SelfRegHarvestFailed(fileSource, tie.Message));
210 }
211 }
212 catch (Exception ex)
213 {
214 this.Core.Messaging.Write(HarvesterWarnings.SelfRegHarvestFailed(fileSource, ex.Message));
215 }
216 }
217 }
218}