aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Util/wixext
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Util/wixext')
-rw-r--r--src/ext/Util/wixext/PerformanceCounterType.cs192
-rw-r--r--src/ext/Util/wixext/Symbols/EventManifestSymbol.cs55
-rw-r--r--src/ext/Util/wixext/Symbols/FileSharePermissionsSymbol.cs63
-rw-r--r--src/ext/Util/wixext/Symbols/FileShareSymbol.cs71
-rw-r--r--src/ext/Util/wixext/Symbols/GroupSymbol.cs63
-rw-r--r--src/ext/Util/wixext/Symbols/PerfmonManifestSymbol.cs63
-rw-r--r--src/ext/Util/wixext/Symbols/PerfmonSymbol.cs63
-rw-r--r--src/ext/Util/wixext/Symbols/PerformanceCategorySymbol.cs71
-rw-r--r--src/ext/Util/wixext/Symbols/SecureObjectsSymbol.cs103
-rw-r--r--src/ext/Util/wixext/Symbols/ServiceConfigSymbol.cs119
-rw-r--r--src/ext/Util/wixext/Symbols/UserGroupSymbol.cs55
-rw-r--r--src/ext/Util/wixext/Symbols/UserSymbol.cs79
-rw-r--r--src/ext/Util/wixext/Symbols/UtilSymbolDefinitions.cs125
-rw-r--r--src/ext/Util/wixext/Symbols/WixCloseApplicationSymbol.cs103
-rw-r--r--src/ext/Util/wixext/Symbols/WixFormatFilesSymbol.cs55
-rw-r--r--src/ext/Util/wixext/Symbols/WixInternetShortcutSymbol.cs95
-rw-r--r--src/ext/Util/wixext/Symbols/WixRemoveFolderExSymbol.cs78
-rw-r--r--src/ext/Util/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs86
-rw-r--r--src/ext/Util/wixext/Symbols/WixRestartResourceSymbol.cs71
-rw-r--r--src/ext/Util/wixext/Symbols/WixTouchFileSymbol.cs63
-rw-r--r--src/ext/Util/wixext/Symbols/WixWindowsFeatureSearchSymbol.cs47
-rw-r--r--src/ext/Util/wixext/Symbols/XmlConfigSymbol.cs111
-rw-r--r--src/ext/Util/wixext/Symbols/XmlFileSymbol.cs95
-rw-r--r--src/ext/Util/wixext/UtilCompiler.cs3889
-rw-r--r--src/ext/Util/wixext/UtilConstants.cs17
-rw-r--r--src/ext/Util/wixext/UtilDecompiler.cs1543
-rw-r--r--src/ext/Util/wixext/UtilErrors.cs49
-rw-r--r--src/ext/Util/wixext/UtilExtensionData.cs23
-rw-r--r--src/ext/Util/wixext/UtilExtensionFactory.cs18
-rw-r--r--src/ext/Util/wixext/UtilTableDefinitions.cs319
-rw-r--r--src/ext/Util/wixext/UtilWarnings.cs37
-rw-r--r--src/ext/Util/wixext/UtilWindowsInstallerBackendExtension.cs13
-rw-r--r--src/ext/Util/wixext/WixToolset.Util.wixext.csproj31
-rw-r--r--src/ext/Util/wixext/WixToolset.Util.wixext.nuspec25
-rw-r--r--src/ext/Util/wixext/WixToolset.Util.wixext.targets11
-rw-r--r--src/ext/Util/wixext/WixToolset.Util.wixext.v3.ncrunchproject7
36 files changed, 7908 insertions, 0 deletions
diff --git a/src/ext/Util/wixext/PerformanceCounterType.cs b/src/ext/Util/wixext/PerformanceCounterType.cs
new file mode 100644
index 00000000..1e06efd3
--- /dev/null
+++ b/src/ext/Util/wixext/PerformanceCounterType.cs
@@ -0,0 +1,192 @@
1// Captured from: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.dll
2
3namespace System.Diagnostics
4{
5 public enum PerformanceCounterType
6 {
7 //
8 // Summary:
9 // An instantaneous counter that shows the most recently observed value in hexadecimal
10 // format. Used, for example, to maintain a simple count of items or operations.
11 NumberOfItemsHEX32 = 0,
12 //
13 // Summary:
14 // An instantaneous counter that shows the most recently observed value. Used, for
15 // example, to maintain a simple count of a very large number of items or operations.
16 // It is the same as NumberOfItemsHEX32 except that it uses larger fields to accommodate
17 // larger values.
18 NumberOfItemsHEX64 = 256,
19 //
20 // Summary:
21 // An instantaneous counter that shows the most recently observed value. Used, for
22 // example, to maintain a simple count of items or operations.
23 NumberOfItems32 = 65536,
24 //
25 // Summary:
26 // An instantaneous counter that shows the most recently observed value. Used, for
27 // example, to maintain a simple count of a very large number of items or operations.
28 // It is the same as NumberOfItems32 except that it uses larger fields to accommodate
29 // larger values.
30 NumberOfItems64 = 65792,
31 //
32 // Summary:
33 // A difference counter that shows the change in the measured attribute between
34 // the two most recent sample intervals.
35 CounterDelta32 = 4195328,
36 //
37 // Summary:
38 // A difference counter that shows the change in the measured attribute between
39 // the two most recent sample intervals. It is the same as the CounterDelta32 counter
40 // type except that is uses larger fields to accomodate larger values.
41 CounterDelta64 = 4195584,
42 //
43 // Summary:
44 // An average counter that shows the average number of operations completed in one
45 // second. When a counter of this type samples the data, each sampling interrupt
46 // returns one or zero. The counter data is the number of ones that were sampled.
47 // It measures time in units of ticks of the system performance timer.
48 SampleCounter = 4260864,
49 //
50 // Summary:
51 // An average counter designed to monitor the average length of a queue to a resource
52 // over time. It shows the difference between the queue lengths observed during
53 // the last two sample intervals divided by the duration of the interval. This type
54 // of counter is typically used to track the number of items that are queued or
55 // waiting.
56 CountPerTimeInterval32 = 4523008,
57 //
58 // Summary:
59 // An average counter that monitors the average length of a queue to a resource
60 // over time. Counters of this type display the difference between the queue lengths
61 // observed during the last two sample intervals, divided by the duration of the
62 // interval. This counter type is the same as CountPerTimeInterval32 except that
63 // it uses larger fields to accommodate larger values. This type of counter is typically
64 // used to track a high-volume or very large number of items that are queued or
65 // waiting.
66 CountPerTimeInterval64 = 4523264,
67 //
68 // Summary:
69 // A difference counter that shows the average number of operations completed during
70 // each second of the sample interval. Counters of this type measure time in ticks
71 // of the system clock.
72 RateOfCountsPerSecond32 = 272696320,
73 //
74 // Summary:
75 // A difference counter that shows the average number of operations completed during
76 // each second of the sample interval. Counters of this type measure time in ticks
77 // of the system clock. This counter type is the same as the RateOfCountsPerSecond32
78 // type, but it uses larger fields to accommodate larger values to track a high-volume
79 // number of items or operations per second, such as a byte-transmission rate.
80 RateOfCountsPerSecond64 = 272696576,
81 //
82 // Summary:
83 // An instantaneous percentage counter that shows the ratio of a subset to its set
84 // as a percentage. For example, it compares the number of bytes in use on a disk
85 // to the total number of bytes on the disk. Counters of this type display the current
86 // percentage only, not an average over time.
87 RawFraction = 537003008,
88 //
89 // Summary:
90 // A percentage counter that shows the average time that a component is active as
91 // a percentage of the total sample time.
92 CounterTimer = 541132032,
93 //
94 // Summary:
95 // A percentage counter that shows the active time of a component as a percentage
96 // of the total elapsed time of the sample interval. It measures time in units of
97 // 100 nanoseconds (ns). Counters of this type are designed to measure the activity
98 // of one component at a time.
99 Timer100Ns = 542180608,
100 //
101 // Summary:
102 // A percentage counter that shows the average ratio of hits to all operations during
103 // the last two sample intervals.
104 SampleFraction = 549585920,
105 //
106 // Summary:
107 // A percentage counter that displays the average percentage of active time observed
108 // during sample interval. The value of these counters is calculated by monitoring
109 // the percentage of time that the service was inactive and then subtracting that
110 // value from 100 percent.
111 CounterTimerInverse = 557909248,
112 //
113 // Summary:
114 // A percentage counter that shows the average percentage of active time observed
115 // during the sample interval.
116 Timer100NsInverse = 558957824,
117 //
118 // Summary:
119 // A percentage counter that displays the active time of one or more components
120 // as a percentage of the total time of the sample interval. Because the numerator
121 // records the active time of components operating simultaneously, the resulting
122 // percentage can exceed 100 percent.
123 CounterMultiTimer = 574686464,
124 //
125 // Summary:
126 // A percentage counter that shows the active time of one or more components as
127 // a percentage of the total time of the sample interval. It measures time in 100
128 // nanosecond (ns) units.
129 CounterMultiTimer100Ns = 575735040,
130 //
131 // Summary:
132 // A percentage counter that shows the active time of one or more components as
133 // a percentage of the total time of the sample interval. It derives the active
134 // time by measuring the time that the components were not active and subtracting
135 // the result from 100 percent by the number of objects monitored.
136 CounterMultiTimerInverse = 591463680,
137 //
138 // Summary:
139 // A percentage counter that shows the active time of one or more components as
140 // a percentage of the total time of the sample interval. Counters of this type
141 // measure time in 100 nanosecond (ns) units. They derive the active time by measuring
142 // the time that the components were not active and subtracting the result from
143 // multiplying 100 percent by the number of objects monitored.
144 CounterMultiTimer100NsInverse = 592512256,
145 //
146 // Summary:
147 // An average counter that measures the time it takes, on average, to complete a
148 // process or operation. Counters of this type display a ratio of the total elapsed
149 // time of the sample interval to the number of processes or operations completed
150 // during that time. This counter type measures time in ticks of the system clock.
151 AverageTimer32 = 805438464,
152 //
153 // Summary:
154 // A difference timer that shows the total time between when the component or process
155 // started and the time when this value is calculated.
156 ElapsedTime = 807666944,
157 //
158 // Summary:
159 // An average counter that shows how many items are processed, on average, during
160 // an operation. Counters of this type display a ratio of the items processed to
161 // the number of operations completed. The ratio is calculated by comparing the
162 // number of items processed during the last interval to the number of operations
163 // completed during the last interval.
164 AverageCount64 = 1073874176,
165 //
166 // Summary:
167 // A base counter that stores the number of sampling interrupts taken and is used
168 // as a denominator in the sampling fraction. The sampling fraction is the number
169 // of samples that were 1 (or true) for a sample interrupt. Check that this value
170 // is greater than zero before using it as the denominator in a calculation of SampleFraction.
171 SampleBase = 1073939457,
172 //
173 // Summary:
174 // A base counter that is used in the calculation of time or count averages, such
175 // as AverageTimer32 and AverageCount64. Stores the denominator for calculating
176 // a counter to present "time per operation" or "count per operation".
177 AverageBase = 1073939458,
178 //
179 // Summary:
180 // A base counter that stores the denominator of a counter that presents a general
181 // arithmetic fraction. Check that this value is greater than zero before using
182 // it as the denominator in a RawFraction value calculation.
183 RawBase = 1073939459,
184 //
185 // Summary:
186 // A base counter that indicates the number of items sampled. It is used as the
187 // denominator in the calculations to get an average among the items sampled when
188 // taking timings of multiple, but similar items. Used with CounterMultiTimer, CounterMultiTimerInverse,
189 // CounterMultiTimer100Ns, and CounterMultiTimer100NsInverse.
190 CounterMultiBase = 1107494144
191 }
192}
diff --git a/src/ext/Util/wixext/Symbols/EventManifestSymbol.cs b/src/ext/Util/wixext/Symbols/EventManifestSymbol.cs
new file mode 100644
index 00000000..ccd3c899
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/EventManifestSymbol.cs
@@ -0,0 +1,55 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition EventManifest = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.EventManifest.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(EventManifestSymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(EventManifestSymbolFields.File), IntermediateFieldType.String),
16 },
17 typeof(EventManifestSymbol));
18 }
19}
20
21namespace WixToolset.Util.Symbols
22{
23 using WixToolset.Data;
24
25 public enum EventManifestSymbolFields
26 {
27 ComponentRef,
28 File,
29 }
30
31 public class EventManifestSymbol : IntermediateSymbol
32 {
33 public EventManifestSymbol() : base(UtilSymbolDefinitions.EventManifest, null, null)
34 {
35 }
36
37 public EventManifestSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.EventManifest, sourceLineNumber, id)
38 {
39 }
40
41 public IntermediateField this[EventManifestSymbolFields index] => this.Fields[(int)index];
42
43 public string ComponentRef
44 {
45 get => this.Fields[(int)EventManifestSymbolFields.ComponentRef].AsString();
46 set => this.Set((int)EventManifestSymbolFields.ComponentRef, value);
47 }
48
49 public string File
50 {
51 get => this.Fields[(int)EventManifestSymbolFields.File].AsString();
52 set => this.Set((int)EventManifestSymbolFields.File, value);
53 }
54 }
55} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/FileSharePermissionsSymbol.cs b/src/ext/Util/wixext/Symbols/FileSharePermissionsSymbol.cs
new file mode 100644
index 00000000..3db92f22
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/FileSharePermissionsSymbol.cs
@@ -0,0 +1,63 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition FileSharePermissions = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.FileSharePermissions.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(FileSharePermissionsSymbolFields.FileShareRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(FileSharePermissionsSymbolFields.UserRef), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(FileSharePermissionsSymbolFields.Permissions), IntermediateFieldType.Number),
17 },
18 typeof(FileSharePermissionsSymbol));
19 }
20}
21
22namespace WixToolset.Util.Symbols
23{
24 using WixToolset.Data;
25
26 public enum FileSharePermissionsSymbolFields
27 {
28 FileShareRef,
29 UserRef,
30 Permissions,
31 }
32
33 public class FileSharePermissionsSymbol : IntermediateSymbol
34 {
35 public FileSharePermissionsSymbol() : base(UtilSymbolDefinitions.FileSharePermissions, null, null)
36 {
37 }
38
39 public FileSharePermissionsSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.FileSharePermissions, sourceLineNumber, id)
40 {
41 }
42
43 public IntermediateField this[FileSharePermissionsSymbolFields index] => this.Fields[(int)index];
44
45 public string FileShareRef
46 {
47 get => this.Fields[(int)FileSharePermissionsSymbolFields.FileShareRef].AsString();
48 set => this.Set((int)FileSharePermissionsSymbolFields.FileShareRef, value);
49 }
50
51 public string UserRef
52 {
53 get => this.Fields[(int)FileSharePermissionsSymbolFields.UserRef].AsString();
54 set => this.Set((int)FileSharePermissionsSymbolFields.UserRef, value);
55 }
56
57 public int Permissions
58 {
59 get => this.Fields[(int)FileSharePermissionsSymbolFields.Permissions].AsNumber();
60 set => this.Set((int)FileSharePermissionsSymbolFields.Permissions, value);
61 }
62 }
63} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/FileShareSymbol.cs b/src/ext/Util/wixext/Symbols/FileShareSymbol.cs
new file mode 100644
index 00000000..c956ff42
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/FileShareSymbol.cs
@@ -0,0 +1,71 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition FileShare = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.FileShare.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(FileShareSymbolFields.ShareName), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(FileShareSymbolFields.ComponentRef), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(FileShareSymbolFields.Description), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(FileShareSymbolFields.DirectoryRef), IntermediateFieldType.String),
18 },
19 typeof(FileShareSymbol));
20 }
21}
22
23namespace WixToolset.Util.Symbols
24{
25 using WixToolset.Data;
26
27 public enum FileShareSymbolFields
28 {
29 ShareName,
30 ComponentRef,
31 Description,
32 DirectoryRef,
33 }
34
35 public class FileShareSymbol : IntermediateSymbol
36 {
37 public FileShareSymbol() : base(UtilSymbolDefinitions.FileShare, null, null)
38 {
39 }
40
41 public FileShareSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.FileShare, sourceLineNumber, id)
42 {
43 }
44
45 public IntermediateField this[FileShareSymbolFields index] => this.Fields[(int)index];
46
47 public string ShareName
48 {
49 get => this.Fields[(int)FileShareSymbolFields.ShareName].AsString();
50 set => this.Set((int)FileShareSymbolFields.ShareName, value);
51 }
52
53 public string ComponentRef
54 {
55 get => this.Fields[(int)FileShareSymbolFields.ComponentRef].AsString();
56 set => this.Set((int)FileShareSymbolFields.ComponentRef, value);
57 }
58
59 public string Description
60 {
61 get => this.Fields[(int)FileShareSymbolFields.Description].AsString();
62 set => this.Set((int)FileShareSymbolFields.Description, value);
63 }
64
65 public string DirectoryRef
66 {
67 get => this.Fields[(int)FileShareSymbolFields.DirectoryRef].AsString();
68 set => this.Set((int)FileShareSymbolFields.DirectoryRef, value);
69 }
70 }
71} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/GroupSymbol.cs b/src/ext/Util/wixext/Symbols/GroupSymbol.cs
new file mode 100644
index 00000000..b378db44
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/GroupSymbol.cs
@@ -0,0 +1,63 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition Group = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.Group.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(GroupSymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(GroupSymbolFields.Name), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(GroupSymbolFields.Domain), IntermediateFieldType.String),
17 },
18 typeof(GroupSymbol));
19 }
20}
21
22namespace WixToolset.Util.Symbols
23{
24 using WixToolset.Data;
25
26 public enum GroupSymbolFields
27 {
28 ComponentRef,
29 Name,
30 Domain,
31 }
32
33 public class GroupSymbol : IntermediateSymbol
34 {
35 public GroupSymbol() : base(UtilSymbolDefinitions.Group, null, null)
36 {
37 }
38
39 public GroupSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.Group, sourceLineNumber, id)
40 {
41 }
42
43 public IntermediateField this[GroupSymbolFields index] => this.Fields[(int)index];
44
45 public string ComponentRef
46 {
47 get => this.Fields[(int)GroupSymbolFields.ComponentRef].AsString();
48 set => this.Set((int)GroupSymbolFields.ComponentRef, value);
49 }
50
51 public string Name
52 {
53 get => this.Fields[(int)GroupSymbolFields.Name].AsString();
54 set => this.Set((int)GroupSymbolFields.Name, value);
55 }
56
57 public string Domain
58 {
59 get => this.Fields[(int)GroupSymbolFields.Domain].AsString();
60 set => this.Set((int)GroupSymbolFields.Domain, value);
61 }
62 }
63} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/PerfmonManifestSymbol.cs b/src/ext/Util/wixext/Symbols/PerfmonManifestSymbol.cs
new file mode 100644
index 00000000..03fef14e
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/PerfmonManifestSymbol.cs
@@ -0,0 +1,63 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition PerfmonManifest = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.PerfmonManifest.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(PerfmonManifestSymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(PerfmonManifestSymbolFields.File), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(PerfmonManifestSymbolFields.ResourceFileDirectory), IntermediateFieldType.String),
17 },
18 typeof(PerfmonManifestSymbol));
19 }
20}
21
22namespace WixToolset.Util.Symbols
23{
24 using WixToolset.Data;
25
26 public enum PerfmonManifestSymbolFields
27 {
28 ComponentRef,
29 File,
30 ResourceFileDirectory,
31 }
32
33 public class PerfmonManifestSymbol : IntermediateSymbol
34 {
35 public PerfmonManifestSymbol() : base(UtilSymbolDefinitions.PerfmonManifest, null, null)
36 {
37 }
38
39 public PerfmonManifestSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.PerfmonManifest, sourceLineNumber, id)
40 {
41 }
42
43 public IntermediateField this[PerfmonManifestSymbolFields index] => this.Fields[(int)index];
44
45 public string ComponentRef
46 {
47 get => this.Fields[(int)PerfmonManifestSymbolFields.ComponentRef].AsString();
48 set => this.Set((int)PerfmonManifestSymbolFields.ComponentRef, value);
49 }
50
51 public string File
52 {
53 get => this.Fields[(int)PerfmonManifestSymbolFields.File].AsString();
54 set => this.Set((int)PerfmonManifestSymbolFields.File, value);
55 }
56
57 public string ResourceFileDirectory
58 {
59 get => this.Fields[(int)PerfmonManifestSymbolFields.ResourceFileDirectory].AsString();
60 set => this.Set((int)PerfmonManifestSymbolFields.ResourceFileDirectory, value);
61 }
62 }
63} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/PerfmonSymbol.cs b/src/ext/Util/wixext/Symbols/PerfmonSymbol.cs
new file mode 100644
index 00000000..6784ebd1
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/PerfmonSymbol.cs
@@ -0,0 +1,63 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition Perfmon = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.Perfmon.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(PerfmonSymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(PerfmonSymbolFields.File), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(PerfmonSymbolFields.Name), IntermediateFieldType.String),
17 },
18 typeof(PerfmonSymbol));
19 }
20}
21
22namespace WixToolset.Util.Symbols
23{
24 using WixToolset.Data;
25
26 public enum PerfmonSymbolFields
27 {
28 ComponentRef,
29 File,
30 Name,
31 }
32
33 public class PerfmonSymbol : IntermediateSymbol
34 {
35 public PerfmonSymbol() : base(UtilSymbolDefinitions.Perfmon, null, null)
36 {
37 }
38
39 public PerfmonSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.Perfmon, sourceLineNumber, id)
40 {
41 }
42
43 public IntermediateField this[PerfmonSymbolFields index] => this.Fields[(int)index];
44
45 public string ComponentRef
46 {
47 get => this.Fields[(int)PerfmonSymbolFields.ComponentRef].AsString();
48 set => this.Set((int)PerfmonSymbolFields.ComponentRef, value);
49 }
50
51 public string File
52 {
53 get => this.Fields[(int)PerfmonSymbolFields.File].AsString();
54 set => this.Set((int)PerfmonSymbolFields.File, value);
55 }
56
57 public string Name
58 {
59 get => this.Fields[(int)PerfmonSymbolFields.Name].AsString();
60 set => this.Set((int)PerfmonSymbolFields.Name, value);
61 }
62 }
63} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/PerformanceCategorySymbol.cs b/src/ext/Util/wixext/Symbols/PerformanceCategorySymbol.cs
new file mode 100644
index 00000000..5ecf388c
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/PerformanceCategorySymbol.cs
@@ -0,0 +1,71 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition PerformanceCategory = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.PerformanceCategory.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.Name), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.IniData), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(PerformanceCategorySymbolFields.ConstantData), IntermediateFieldType.String),
18 },
19 typeof(PerformanceCategorySymbol));
20 }
21}
22
23namespace WixToolset.Util.Symbols
24{
25 using WixToolset.Data;
26
27 public enum PerformanceCategorySymbolFields
28 {
29 ComponentRef,
30 Name,
31 IniData,
32 ConstantData,
33 }
34
35 public class PerformanceCategorySymbol : IntermediateSymbol
36 {
37 public PerformanceCategorySymbol() : base(UtilSymbolDefinitions.PerformanceCategory, null, null)
38 {
39 }
40
41 public PerformanceCategorySymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.PerformanceCategory, sourceLineNumber, id)
42 {
43 }
44
45 public IntermediateField this[PerformanceCategorySymbolFields index] => this.Fields[(int)index];
46
47 public string ComponentRef
48 {
49 get => this.Fields[(int)PerformanceCategorySymbolFields.ComponentRef].AsString();
50 set => this.Set((int)PerformanceCategorySymbolFields.ComponentRef, value);
51 }
52
53 public string Name
54 {
55 get => this.Fields[(int)PerformanceCategorySymbolFields.Name].AsString();
56 set => this.Set((int)PerformanceCategorySymbolFields.Name, value);
57 }
58
59 public string IniData
60 {
61 get => this.Fields[(int)PerformanceCategorySymbolFields.IniData].AsString();
62 set => this.Set((int)PerformanceCategorySymbolFields.IniData, value);
63 }
64
65 public string ConstantData
66 {
67 get => this.Fields[(int)PerformanceCategorySymbolFields.ConstantData].AsString();
68 set => this.Set((int)PerformanceCategorySymbolFields.ConstantData, value);
69 }
70 }
71} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/SecureObjectsSymbol.cs b/src/ext/Util/wixext/Symbols/SecureObjectsSymbol.cs
new file mode 100644
index 00000000..25fc6dca
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/SecureObjectsSymbol.cs
@@ -0,0 +1,103 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition SecureObjects = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.SecureObjects.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.SecureObject), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Table), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Domain), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.User), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Attributes), IntermediateFieldType.Number),
19 new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.Permission), IntermediateFieldType.Number),
20 new IntermediateFieldDefinition(nameof(SecureObjectsSymbolFields.ComponentRef), IntermediateFieldType.String),
21 },
22 typeof(SecureObjectsSymbol));
23 }
24}
25
26namespace WixToolset.Util.Symbols
27{
28 using System;
29 using WixToolset.Data;
30
31 public enum SecureObjectsSymbolFields
32 {
33 SecureObject,
34 Table,
35 Domain,
36 User,
37 Attributes,
38 Permission,
39 ComponentRef,
40 }
41
42 [Flags]
43 public enum WixPermissionExAttributes
44 {
45 None = 0x0,
46 Inheritable = 0x01
47 }
48
49 public class SecureObjectsSymbol : IntermediateSymbol
50 {
51 public SecureObjectsSymbol() : base(UtilSymbolDefinitions.SecureObjects, null, null)
52 {
53 }
54
55 public SecureObjectsSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.SecureObjects, sourceLineNumber, id)
56 {
57 }
58
59 public IntermediateField this[SecureObjectsSymbolFields index] => this.Fields[(int)index];
60
61 public string SecureObject
62 {
63 get => this.Fields[(int)SecureObjectsSymbolFields.SecureObject].AsString();
64 set => this.Set((int)SecureObjectsSymbolFields.SecureObject, value);
65 }
66
67 public string Table
68 {
69 get => this.Fields[(int)SecureObjectsSymbolFields.Table].AsString();
70 set => this.Set((int)SecureObjectsSymbolFields.Table, value);
71 }
72
73 public string Domain
74 {
75 get => this.Fields[(int)SecureObjectsSymbolFields.Domain].AsString();
76 set => this.Set((int)SecureObjectsSymbolFields.Domain, value);
77 }
78
79 public string User
80 {
81 get => this.Fields[(int)SecureObjectsSymbolFields.User].AsString();
82 set => this.Set((int)SecureObjectsSymbolFields.User, value);
83 }
84
85 public WixPermissionExAttributes Attributes
86 {
87 get => (WixPermissionExAttributes)this.Fields[(int)SecureObjectsSymbolFields.Attributes].AsNumber();
88 set => this.Set((int)SecureObjectsSymbolFields.Attributes, (int)value);
89 }
90
91 public int? Permission
92 {
93 get => this.Fields[(int)SecureObjectsSymbolFields.Permission].AsNullableNumber();
94 set => this.Set((int)SecureObjectsSymbolFields.Permission, value);
95 }
96
97 public string ComponentRef
98 {
99 get => this.Fields[(int)SecureObjectsSymbolFields.ComponentRef].AsString();
100 set => this.Set((int)SecureObjectsSymbolFields.ComponentRef, value);
101 }
102 }
103} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/ServiceConfigSymbol.cs b/src/ext/Util/wixext/Symbols/ServiceConfigSymbol.cs
new file mode 100644
index 00000000..3a877f9b
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/ServiceConfigSymbol.cs
@@ -0,0 +1,119 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition ServiceConfig = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.ServiceConfig.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ServiceName), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ComponentRef), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.NewService), IntermediateFieldType.Number),
17 new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.FirstFailureActionType), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.SecondFailureActionType), IntermediateFieldType.String),
19 new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ThirdFailureActionType), IntermediateFieldType.String),
20 new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ResetPeriodInDays), IntermediateFieldType.Number),
21 new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.RestartServiceDelayInSeconds), IntermediateFieldType.Number),
22 new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.ProgramCommandLine), IntermediateFieldType.String),
23 new IntermediateFieldDefinition(nameof(ServiceConfigSymbolFields.RebootMessage), IntermediateFieldType.String),
24 },
25 typeof(ServiceConfigSymbol));
26 }
27}
28
29namespace WixToolset.Util.Symbols
30{
31 using WixToolset.Data;
32
33 public enum ServiceConfigSymbolFields
34 {
35 ServiceName,
36 ComponentRef,
37 NewService,
38 FirstFailureActionType,
39 SecondFailureActionType,
40 ThirdFailureActionType,
41 ResetPeriodInDays,
42 RestartServiceDelayInSeconds,
43 ProgramCommandLine,
44 RebootMessage,
45 }
46
47 public class ServiceConfigSymbol : IntermediateSymbol
48 {
49 public ServiceConfigSymbol() : base(UtilSymbolDefinitions.ServiceConfig, null, null)
50 {
51 }
52
53 public ServiceConfigSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.ServiceConfig, sourceLineNumber, id)
54 {
55 }
56
57 public IntermediateField this[ServiceConfigSymbolFields index] => this.Fields[(int)index];
58
59 public string ServiceName
60 {
61 get => this.Fields[(int)ServiceConfigSymbolFields.ServiceName].AsString();
62 set => this.Set((int)ServiceConfigSymbolFields.ServiceName, value);
63 }
64
65 public string ComponentRef
66 {
67 get => this.Fields[(int)ServiceConfigSymbolFields.ComponentRef].AsString();
68 set => this.Set((int)ServiceConfigSymbolFields.ComponentRef, value);
69 }
70
71 public int NewService
72 {
73 get => this.Fields[(int)ServiceConfigSymbolFields.NewService].AsNumber();
74 set => this.Set((int)ServiceConfigSymbolFields.NewService, value);
75 }
76
77 public string FirstFailureActionType
78 {
79 get => this.Fields[(int)ServiceConfigSymbolFields.FirstFailureActionType].AsString();
80 set => this.Set((int)ServiceConfigSymbolFields.FirstFailureActionType, value);
81 }
82
83 public string SecondFailureActionType
84 {
85 get => this.Fields[(int)ServiceConfigSymbolFields.SecondFailureActionType].AsString();
86 set => this.Set((int)ServiceConfigSymbolFields.SecondFailureActionType, value);
87 }
88
89 public string ThirdFailureActionType
90 {
91 get => this.Fields[(int)ServiceConfigSymbolFields.ThirdFailureActionType].AsString();
92 set => this.Set((int)ServiceConfigSymbolFields.ThirdFailureActionType, value);
93 }
94
95 public int? ResetPeriodInDays
96 {
97 get => this.Fields[(int)ServiceConfigSymbolFields.ResetPeriodInDays].AsNullableNumber();
98 set => this.Set((int)ServiceConfigSymbolFields.ResetPeriodInDays, value);
99 }
100
101 public int? RestartServiceDelayInSeconds
102 {
103 get => this.Fields[(int)ServiceConfigSymbolFields.RestartServiceDelayInSeconds].AsNullableNumber();
104 set => this.Set((int)ServiceConfigSymbolFields.RestartServiceDelayInSeconds, value);
105 }
106
107 public string ProgramCommandLine
108 {
109 get => this.Fields[(int)ServiceConfigSymbolFields.ProgramCommandLine].AsString();
110 set => this.Set((int)ServiceConfigSymbolFields.ProgramCommandLine, value);
111 }
112
113 public string RebootMessage
114 {
115 get => this.Fields[(int)ServiceConfigSymbolFields.RebootMessage].AsString();
116 set => this.Set((int)ServiceConfigSymbolFields.RebootMessage, value);
117 }
118 }
119} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/UserGroupSymbol.cs b/src/ext/Util/wixext/Symbols/UserGroupSymbol.cs
new file mode 100644
index 00000000..c8f3998e
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/UserGroupSymbol.cs
@@ -0,0 +1,55 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition UserGroup = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.UserGroup.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(UserGroupSymbolFields.UserRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(UserGroupSymbolFields.GroupRef), IntermediateFieldType.String),
16 },
17 typeof(UserGroupSymbol));
18 }
19}
20
21namespace WixToolset.Util.Symbols
22{
23 using WixToolset.Data;
24
25 public enum UserGroupSymbolFields
26 {
27 UserRef,
28 GroupRef,
29 }
30
31 public class UserGroupSymbol : IntermediateSymbol
32 {
33 public UserGroupSymbol() : base(UtilSymbolDefinitions.UserGroup, null, null)
34 {
35 }
36
37 public UserGroupSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.UserGroup, sourceLineNumber, id)
38 {
39 }
40
41 public IntermediateField this[UserGroupSymbolFields index] => this.Fields[(int)index];
42
43 public string UserRef
44 {
45 get => this.Fields[(int)UserGroupSymbolFields.UserRef].AsString();
46 set => this.Set((int)UserGroupSymbolFields.UserRef, value);
47 }
48
49 public string GroupRef
50 {
51 get => this.Fields[(int)UserGroupSymbolFields.GroupRef].AsString();
52 set => this.Set((int)UserGroupSymbolFields.GroupRef, value);
53 }
54 }
55} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/UserSymbol.cs b/src/ext/Util/wixext/Symbols/UserSymbol.cs
new file mode 100644
index 00000000..5f00064b
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/UserSymbol.cs
@@ -0,0 +1,79 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition User = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.User.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(UserSymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(UserSymbolFields.Name), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(UserSymbolFields.Domain), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(UserSymbolFields.Password), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(UserSymbolFields.Attributes), IntermediateFieldType.Number),
19 },
20 typeof(UserSymbol));
21 }
22}
23
24namespace WixToolset.Util.Symbols
25{
26 using WixToolset.Data;
27
28 public enum UserSymbolFields
29 {
30 ComponentRef,
31 Name,
32 Domain,
33 Password,
34 Attributes,
35 }
36
37 public class UserSymbol : IntermediateSymbol
38 {
39 public UserSymbol() : base(UtilSymbolDefinitions.User, null, null)
40 {
41 }
42
43 public UserSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.User, sourceLineNumber, id)
44 {
45 }
46
47 public IntermediateField this[UserSymbolFields index] => this.Fields[(int)index];
48
49 public string ComponentRef
50 {
51 get => this.Fields[(int)UserSymbolFields.ComponentRef].AsString();
52 set => this.Set((int)UserSymbolFields.ComponentRef, value);
53 }
54
55 public string Name
56 {
57 get => this.Fields[(int)UserSymbolFields.Name].AsString();
58 set => this.Set((int)UserSymbolFields.Name, value);
59 }
60
61 public string Domain
62 {
63 get => this.Fields[(int)UserSymbolFields.Domain].AsString();
64 set => this.Set((int)UserSymbolFields.Domain, value);
65 }
66
67 public string Password
68 {
69 get => this.Fields[(int)UserSymbolFields.Password].AsString();
70 set => this.Set((int)UserSymbolFields.Password, value);
71 }
72
73 public int Attributes
74 {
75 get => this.Fields[(int)UserSymbolFields.Attributes].AsNumber();
76 set => this.Set((int)UserSymbolFields.Attributes, value);
77 }
78 }
79} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/UtilSymbolDefinitions.cs b/src/ext/Util/wixext/Symbols/UtilSymbolDefinitions.cs
new file mode 100644
index 00000000..72091c3b
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/UtilSymbolDefinitions.cs
@@ -0,0 +1,125 @@
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.Util
4{
5 using System;
6 using WixToolset.Data;
7 using WixToolset.Data.Burn;
8
9 public enum UtilSymbolDefinitionType
10 {
11 EventManifest,
12 FileShare,
13 FileSharePermissions,
14 Group,
15 Perfmon,
16 PerfmonManifest,
17 PerformanceCategory,
18 SecureObjects,
19 ServiceConfig,
20 User,
21 UserGroup,
22 WixCloseApplication,
23 WixFormatFiles,
24 WixInternetShortcut,
25 WixRemoveFolderEx,
26 WixRemoveRegistryKeyEx,
27 WixRestartResource,
28 WixTouchFile,
29 WixWindowsFeatureSearch,
30 XmlConfig,
31 XmlFile,
32 }
33
34 public static partial class UtilSymbolDefinitions
35 {
36 public static readonly Version Version = new Version("4.0.0");
37
38 public static IntermediateSymbolDefinition ByName(string name)
39 {
40 if (!Enum.TryParse(name, out UtilSymbolDefinitionType type))
41 {
42 return null;
43 }
44
45 return ByType(type);
46 }
47
48 public static IntermediateSymbolDefinition ByType(UtilSymbolDefinitionType type)
49 {
50 switch (type)
51 {
52 case UtilSymbolDefinitionType.EventManifest:
53 return UtilSymbolDefinitions.EventManifest;
54
55 case UtilSymbolDefinitionType.FileShare:
56 return UtilSymbolDefinitions.FileShare;
57
58 case UtilSymbolDefinitionType.FileSharePermissions:
59 return UtilSymbolDefinitions.FileSharePermissions;
60
61 case UtilSymbolDefinitionType.Group:
62 return UtilSymbolDefinitions.Group;
63
64 case UtilSymbolDefinitionType.Perfmon:
65 return UtilSymbolDefinitions.Perfmon;
66
67 case UtilSymbolDefinitionType.PerfmonManifest:
68 return UtilSymbolDefinitions.PerfmonManifest;
69
70 case UtilSymbolDefinitionType.PerformanceCategory:
71 return UtilSymbolDefinitions.PerformanceCategory;
72
73 case UtilSymbolDefinitionType.SecureObjects:
74 return UtilSymbolDefinitions.SecureObjects;
75
76 case UtilSymbolDefinitionType.ServiceConfig:
77 return UtilSymbolDefinitions.ServiceConfig;
78
79 case UtilSymbolDefinitionType.User:
80 return UtilSymbolDefinitions.User;
81
82 case UtilSymbolDefinitionType.UserGroup:
83 return UtilSymbolDefinitions.UserGroup;
84
85 case UtilSymbolDefinitionType.WixCloseApplication:
86 return UtilSymbolDefinitions.WixCloseApplication;
87
88 case UtilSymbolDefinitionType.WixFormatFiles:
89 return UtilSymbolDefinitions.WixFormatFiles;
90
91 case UtilSymbolDefinitionType.WixInternetShortcut:
92 return UtilSymbolDefinitions.WixInternetShortcut;
93
94 case UtilSymbolDefinitionType.WixRemoveFolderEx:
95 return UtilSymbolDefinitions.WixRemoveFolderEx;
96
97 case UtilSymbolDefinitionType.WixRemoveRegistryKeyEx:
98 return UtilSymbolDefinitions.WixRemoveRegistryKeyEx;
99
100 case UtilSymbolDefinitionType.WixRestartResource:
101 return UtilSymbolDefinitions.WixRestartResource;
102
103 case UtilSymbolDefinitionType.WixTouchFile:
104 return UtilSymbolDefinitions.WixTouchFile;
105
106 case UtilSymbolDefinitionType.WixWindowsFeatureSearch:
107 return UtilSymbolDefinitions.WixWindowsFeatureSearch;
108
109 case UtilSymbolDefinitionType.XmlConfig:
110 return UtilSymbolDefinitions.XmlConfig;
111
112 case UtilSymbolDefinitionType.XmlFile:
113 return UtilSymbolDefinitions.XmlFile;
114
115 default:
116 throw new ArgumentOutOfRangeException(nameof(type));
117 }
118 }
119
120 static UtilSymbolDefinitions()
121 {
122 WixWindowsFeatureSearch.AddTag(BurnConstants.BundleExtensionSearchSymbolDefinitionTag);
123 }
124 }
125}
diff --git a/src/ext/Util/wixext/Symbols/WixCloseApplicationSymbol.cs b/src/ext/Util/wixext/Symbols/WixCloseApplicationSymbol.cs
new file mode 100644
index 00000000..0738e3e4
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/WixCloseApplicationSymbol.cs
@@ -0,0 +1,103 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition WixCloseApplication = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.WixCloseApplication.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Target), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Description), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Condition), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Attributes), IntermediateFieldType.Number),
18 new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Sequence), IntermediateFieldType.Number),
19 new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Property), IntermediateFieldType.String),
20 new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.TerminateExitCode), IntermediateFieldType.Number),
21 new IntermediateFieldDefinition(nameof(WixCloseApplicationSymbolFields.Timeout), IntermediateFieldType.Number),
22 },
23 typeof(WixCloseApplicationSymbol));
24 }
25}
26
27namespace WixToolset.Util.Symbols
28{
29 using WixToolset.Data;
30
31 public enum WixCloseApplicationSymbolFields
32 {
33 Target,
34 Description,
35 Condition,
36 Attributes,
37 Sequence,
38 Property,
39 TerminateExitCode,
40 Timeout,
41 }
42
43 public class WixCloseApplicationSymbol : IntermediateSymbol
44 {
45 public WixCloseApplicationSymbol() : base(UtilSymbolDefinitions.WixCloseApplication, null, null)
46 {
47 }
48
49 public WixCloseApplicationSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixCloseApplication, sourceLineNumber, id)
50 {
51 }
52
53 public IntermediateField this[WixCloseApplicationSymbolFields index] => this.Fields[(int)index];
54
55 public string Target
56 {
57 get => this.Fields[(int)WixCloseApplicationSymbolFields.Target].AsString();
58 set => this.Set((int)WixCloseApplicationSymbolFields.Target, value);
59 }
60
61 public string Description
62 {
63 get => this.Fields[(int)WixCloseApplicationSymbolFields.Description].AsString();
64 set => this.Set((int)WixCloseApplicationSymbolFields.Description, value);
65 }
66
67 public string Condition
68 {
69 get => this.Fields[(int)WixCloseApplicationSymbolFields.Condition].AsString();
70 set => this.Set((int)WixCloseApplicationSymbolFields.Condition, value);
71 }
72
73 public int Attributes
74 {
75 get => this.Fields[(int)WixCloseApplicationSymbolFields.Attributes].AsNumber();
76 set => this.Set((int)WixCloseApplicationSymbolFields.Attributes, value);
77 }
78
79 public int? Sequence
80 {
81 get => this.Fields[(int)WixCloseApplicationSymbolFields.Sequence].AsNullableNumber();
82 set => this.Set((int)WixCloseApplicationSymbolFields.Sequence, value);
83 }
84
85 public string Property
86 {
87 get => this.Fields[(int)WixCloseApplicationSymbolFields.Property].AsString();
88 set => this.Set((int)WixCloseApplicationSymbolFields.Property, value);
89 }
90
91 public int? TerminateExitCode
92 {
93 get => this.Fields[(int)WixCloseApplicationSymbolFields.TerminateExitCode].AsNullableNumber();
94 set => this.Set((int)WixCloseApplicationSymbolFields.TerminateExitCode, value);
95 }
96
97 public int? Timeout
98 {
99 get => this.Fields[(int)WixCloseApplicationSymbolFields.Timeout].AsNullableNumber();
100 set => this.Set((int)WixCloseApplicationSymbolFields.Timeout, value);
101 }
102 }
103} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/WixFormatFilesSymbol.cs b/src/ext/Util/wixext/Symbols/WixFormatFilesSymbol.cs
new file mode 100644
index 00000000..38a9b8ff
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/WixFormatFilesSymbol.cs
@@ -0,0 +1,55 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition WixFormatFiles = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.WixFormatFiles.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(WixFormatFilesSymbolFields.BinaryRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixFormatFilesSymbolFields.FileRef), IntermediateFieldType.String),
16 },
17 typeof(WixFormatFilesSymbol));
18 }
19}
20
21namespace WixToolset.Util.Symbols
22{
23 using WixToolset.Data;
24
25 public enum WixFormatFilesSymbolFields
26 {
27 BinaryRef,
28 FileRef,
29 }
30
31 public class WixFormatFilesSymbol : IntermediateSymbol
32 {
33 public WixFormatFilesSymbol() : base(UtilSymbolDefinitions.WixFormatFiles, null, null)
34 {
35 }
36
37 public WixFormatFilesSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixFormatFiles, sourceLineNumber, id)
38 {
39 }
40
41 public IntermediateField this[WixFormatFilesSymbolFields index] => this.Fields[(int)index];
42
43 public string BinaryRef
44 {
45 get => this.Fields[(int)WixFormatFilesSymbolFields.BinaryRef].AsString();
46 set => this.Set((int)WixFormatFilesSymbolFields.BinaryRef, value);
47 }
48
49 public string FileRef
50 {
51 get => this.Fields[(int)WixFormatFilesSymbolFields.FileRef].AsString();
52 set => this.Set((int)WixFormatFilesSymbolFields.FileRef, value);
53 }
54 }
55} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/WixInternetShortcutSymbol.cs b/src/ext/Util/wixext/Symbols/WixInternetShortcutSymbol.cs
new file mode 100644
index 00000000..e8265e02
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/WixInternetShortcutSymbol.cs
@@ -0,0 +1,95 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition WixInternetShortcut = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.WixInternetShortcut.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.DirectoryRef), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.Name), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.Target), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.Attributes), IntermediateFieldType.Number),
19 new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.IconFile), IntermediateFieldType.String),
20 new IntermediateFieldDefinition(nameof(WixInternetShortcutSymbolFields.IconIndex), IntermediateFieldType.Number),
21 },
22 typeof(WixInternetShortcutSymbol));
23 }
24}
25
26namespace WixToolset.Util.Symbols
27{
28 using WixToolset.Data;
29
30 public enum WixInternetShortcutSymbolFields
31 {
32 ComponentRef,
33 DirectoryRef,
34 Name,
35 Target,
36 Attributes,
37 IconFile,
38 IconIndex,
39 }
40
41 public class WixInternetShortcutSymbol : IntermediateSymbol
42 {
43 public WixInternetShortcutSymbol() : base(UtilSymbolDefinitions.WixInternetShortcut, null, null)
44 {
45 }
46
47 public WixInternetShortcutSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixInternetShortcut, sourceLineNumber, id)
48 {
49 }
50
51 public IntermediateField this[WixInternetShortcutSymbolFields index] => this.Fields[(int)index];
52
53 public string ComponentRef
54 {
55 get => this.Fields[(int)WixInternetShortcutSymbolFields.ComponentRef].AsString();
56 set => this.Set((int)WixInternetShortcutSymbolFields.ComponentRef, value);
57 }
58
59 public string DirectoryRef
60 {
61 get => this.Fields[(int)WixInternetShortcutSymbolFields.DirectoryRef].AsString();
62 set => this.Set((int)WixInternetShortcutSymbolFields.DirectoryRef, value);
63 }
64
65 public string Name
66 {
67 get => this.Fields[(int)WixInternetShortcutSymbolFields.Name].AsString();
68 set => this.Set((int)WixInternetShortcutSymbolFields.Name, value);
69 }
70
71 public string Target
72 {
73 get => this.Fields[(int)WixInternetShortcutSymbolFields.Target].AsString();
74 set => this.Set((int)WixInternetShortcutSymbolFields.Target, value);
75 }
76
77 public int Attributes
78 {
79 get => this.Fields[(int)WixInternetShortcutSymbolFields.Attributes].AsNumber();
80 set => this.Set((int)WixInternetShortcutSymbolFields.Attributes, value);
81 }
82
83 public string IconFile
84 {
85 get => this.Fields[(int)WixInternetShortcutSymbolFields.IconFile].AsString();
86 set => this.Set((int)WixInternetShortcutSymbolFields.IconFile, value);
87 }
88
89 public int? IconIndex
90 {
91 get => this.Fields[(int)WixInternetShortcutSymbolFields.IconIndex].AsNullableNumber();
92 set => this.Set((int)WixInternetShortcutSymbolFields.IconIndex, value);
93 }
94 }
95} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/WixRemoveFolderExSymbol.cs b/src/ext/Util/wixext/Symbols/WixRemoveFolderExSymbol.cs
new file mode 100644
index 00000000..86352b6c
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/WixRemoveFolderExSymbol.cs
@@ -0,0 +1,78 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition WixRemoveFolderEx = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.WixRemoveFolderEx.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.Property), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.InstallMode), IntermediateFieldType.Number),
17 new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.Condition), IntermediateFieldType.String),
18 },
19 typeof(WixRemoveFolderExSymbol));
20 }
21}
22
23namespace WixToolset.Util.Symbols
24{
25 using WixToolset.Data;
26
27 public enum WixRemoveFolderExSymbolFields
28 {
29 ComponentRef,
30 Property,
31 InstallMode,
32 Condition,
33 }
34
35 public enum WixRemoveFolderExInstallMode
36 {
37 Install = 1,
38 Uninstall = 2,
39 Both = 3,
40 }
41
42 public class WixRemoveFolderExSymbol : IntermediateSymbol
43 {
44 public WixRemoveFolderExSymbol() : base(UtilSymbolDefinitions.WixRemoveFolderEx, null, null)
45 {
46 }
47
48 public WixRemoveFolderExSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixRemoveFolderEx, sourceLineNumber, id)
49 {
50 }
51
52 public IntermediateField this[WixRemoveFolderExSymbolFields index] => this.Fields[(int)index];
53
54 public string ComponentRef
55 {
56 get => this.Fields[(int)WixRemoveFolderExSymbolFields.ComponentRef].AsString();
57 set => this.Set((int)WixRemoveFolderExSymbolFields.ComponentRef, value);
58 }
59
60 public string Property
61 {
62 get => this.Fields[(int)WixRemoveFolderExSymbolFields.Property].AsString();
63 set => this.Set((int)WixRemoveFolderExSymbolFields.Property, value);
64 }
65
66 public WixRemoveFolderExInstallMode InstallMode
67 {
68 get => (WixRemoveFolderExInstallMode)this.Fields[(int)WixRemoveFolderExSymbolFields.InstallMode].AsNumber();
69 set => this.Set((int)WixRemoveFolderExSymbolFields.InstallMode, (int)value);
70 }
71
72 public string Condition
73 {
74 get => this.Fields[(int)WixRemoveFolderExSymbolFields.Condition].AsString();
75 set => this.Set((int)WixRemoveFolderExSymbolFields.Condition, value);
76 }
77 }
78} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs b/src/ext/Util/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs
new file mode 100644
index 00000000..8e4bd212
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/WixRemoveRegistryKeyExSymbol.cs
@@ -0,0 +1,86 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition WixRemoveRegistryKeyEx = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.WixRemoveRegistryKeyEx.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.Root), IntermediateFieldType.Number),
16 new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.Key), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.InstallMode), IntermediateFieldType.Number),
18 new IntermediateFieldDefinition(nameof(WixRemoveRegistryKeyExSymbolFields.Condition), IntermediateFieldType.String),
19 },
20 typeof(WixRemoveRegistryKeyExSymbol));
21 }
22}
23
24namespace WixToolset.Util.Symbols
25{
26 using WixToolset.Data;
27 using WixToolset.Data.Symbols;
28
29 public enum WixRemoveRegistryKeyExSymbolFields
30 {
31 ComponentRef,
32 Root,
33 Key,
34 InstallMode,
35 Condition,
36 }
37
38 public enum WixRemoveRegistryKeyExInstallMode
39 {
40 Install = 1,
41 Uninstall = 2,
42 }
43
44 public class WixRemoveRegistryKeyExSymbol : IntermediateSymbol
45 {
46 public WixRemoveRegistryKeyExSymbol() : base(UtilSymbolDefinitions.WixRemoveRegistryKeyEx, null, null)
47 {
48 }
49
50 public WixRemoveRegistryKeyExSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixRemoveRegistryKeyEx, sourceLineNumber, id)
51 {
52 }
53
54 public IntermediateField this[WixRemoveRegistryKeyExSymbolFields index] => this.Fields[(int)index];
55
56 public string ComponentRef
57 {
58 get => this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.ComponentRef].AsString();
59 set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.ComponentRef, value);
60 }
61
62 public RegistryRootType Root
63 {
64 get => (RegistryRootType)this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.Root].AsNumber();
65 set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.Root, (int)value);
66 }
67
68 public string Key
69 {
70 get => (string)this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.Key];
71 set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.Key, value);
72 }
73
74 public WixRemoveRegistryKeyExInstallMode InstallMode
75 {
76 get => (WixRemoveRegistryKeyExInstallMode)this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.InstallMode].AsNumber();
77 set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.InstallMode, (int)value);
78 }
79
80 public string Condition
81 {
82 get => this.Fields[(int)WixRemoveRegistryKeyExSymbolFields.Condition].AsString();
83 set => this.Set((int)WixRemoveRegistryKeyExSymbolFields.Condition, value);
84 }
85 }
86}
diff --git a/src/ext/Util/wixext/Symbols/WixRestartResourceSymbol.cs b/src/ext/Util/wixext/Symbols/WixRestartResourceSymbol.cs
new file mode 100644
index 00000000..01b92b63
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/WixRestartResourceSymbol.cs
@@ -0,0 +1,71 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition WixRestartResource = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.WixRestartResource.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(WixRestartResourceSymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixRestartResourceSymbolFields.Resource), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixRestartResourceSymbolFields.Attributes), IntermediateFieldType.Number),
17 },
18 typeof(WixRestartResourceSymbol));
19 }
20}
21
22namespace WixToolset.Util.Symbols
23{
24 using WixToolset.Data;
25
26 public enum WixRestartResourceSymbolFields
27 {
28 ComponentRef,
29 Resource,
30 Attributes,
31 }
32
33 public enum WixRestartResourceAttributes
34 {
35 Filename = 1,
36 ProcessName,
37 ServiceName,
38 TypeMask = 0xf,
39 }
40
41 public class WixRestartResourceSymbol : IntermediateSymbol
42 {
43 public WixRestartResourceSymbol() : base(UtilSymbolDefinitions.WixRestartResource, null, null)
44 {
45 }
46
47 public WixRestartResourceSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixRestartResource, sourceLineNumber, id)
48 {
49 }
50
51 public IntermediateField this[WixRestartResourceSymbolFields index] => this.Fields[(int)index];
52
53 public string ComponentRef
54 {
55 get => this.Fields[(int)WixRestartResourceSymbolFields.ComponentRef].AsString();
56 set => this.Set((int)WixRestartResourceSymbolFields.ComponentRef, value);
57 }
58
59 public string Resource
60 {
61 get => this.Fields[(int)WixRestartResourceSymbolFields.Resource].AsString();
62 set => this.Set((int)WixRestartResourceSymbolFields.Resource, value);
63 }
64
65 public WixRestartResourceAttributes? Attributes
66 {
67 get => (WixRestartResourceAttributes?)this.Fields[(int)WixRestartResourceSymbolFields.Attributes].AsNullableNumber();
68 set => this.Set((int)WixRestartResourceSymbolFields.Attributes, (int?)value);
69 }
70 }
71} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/WixTouchFileSymbol.cs b/src/ext/Util/wixext/Symbols/WixTouchFileSymbol.cs
new file mode 100644
index 00000000..447c21ba
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/WixTouchFileSymbol.cs
@@ -0,0 +1,63 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition WixTouchFile = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.WixTouchFile.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(WixTouchFileSymbolFields.ComponentRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixTouchFileSymbolFields.Path), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixTouchFileSymbolFields.Attributes), IntermediateFieldType.Number),
17 },
18 typeof(WixTouchFileSymbol));
19 }
20}
21
22namespace WixToolset.Util.Symbols
23{
24 using WixToolset.Data;
25
26 public enum WixTouchFileSymbolFields
27 {
28 ComponentRef,
29 Path,
30 Attributes,
31 }
32
33 public class WixTouchFileSymbol : IntermediateSymbol
34 {
35 public WixTouchFileSymbol() : base(UtilSymbolDefinitions.WixTouchFile, null, null)
36 {
37 }
38
39 public WixTouchFileSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixTouchFile, sourceLineNumber, id)
40 {
41 }
42
43 public IntermediateField this[WixTouchFileSymbolFields index] => this.Fields[(int)index];
44
45 public string ComponentRef
46 {
47 get => this.Fields[(int)WixTouchFileSymbolFields.ComponentRef].AsString();
48 set => this.Set((int)WixTouchFileSymbolFields.ComponentRef, value);
49 }
50
51 public string Path
52 {
53 get => this.Fields[(int)WixTouchFileSymbolFields.Path].AsString();
54 set => this.Set((int)WixTouchFileSymbolFields.Path, value);
55 }
56
57 public int Attributes
58 {
59 get => this.Fields[(int)WixTouchFileSymbolFields.Attributes].AsNumber();
60 set => this.Set((int)WixTouchFileSymbolFields.Attributes, value);
61 }
62 }
63} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/WixWindowsFeatureSearchSymbol.cs b/src/ext/Util/wixext/Symbols/WixWindowsFeatureSearchSymbol.cs
new file mode 100644
index 00000000..9a43692c
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/WixWindowsFeatureSearchSymbol.cs
@@ -0,0 +1,47 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition WixWindowsFeatureSearch = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.WixWindowsFeatureSearch.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(WixWindowsFeatureSearchSymbolFields.Type), IntermediateFieldType.String),
15 },
16 typeof(WixWindowsFeatureSearchSymbol));
17 }
18}
19
20namespace WixToolset.Util.Symbols
21{
22 using WixToolset.Data;
23
24 public enum WixWindowsFeatureSearchSymbolFields
25 {
26 Type,
27 }
28
29 public class WixWindowsFeatureSearchSymbol : IntermediateSymbol
30 {
31 public WixWindowsFeatureSearchSymbol() : base(UtilSymbolDefinitions.WixWindowsFeatureSearch, null, null)
32 {
33 }
34
35 public WixWindowsFeatureSearchSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.WixWindowsFeatureSearch, sourceLineNumber, id)
36 {
37 }
38
39 public IntermediateField this[WixWindowsFeatureSearchSymbolFields index] => this.Fields[(int)index];
40
41 public string Type
42 {
43 get => this.Fields[(int)WixWindowsFeatureSearchSymbolFields.Type].AsString();
44 set => this.Set((int)WixWindowsFeatureSearchSymbolFields.Type, value);
45 }
46 }
47}
diff --git a/src/ext/Util/wixext/Symbols/XmlConfigSymbol.cs b/src/ext/Util/wixext/Symbols/XmlConfigSymbol.cs
new file mode 100644
index 00000000..6503a586
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/XmlConfigSymbol.cs
@@ -0,0 +1,111 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition XmlConfig = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.XmlConfig.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.File), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.ElementId), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.ElementPath), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.VerifyPath), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Name), IntermediateFieldType.String),
19 new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Value), IntermediateFieldType.String),
20 new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Flags), IntermediateFieldType.Number),
21 new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.ComponentRef), IntermediateFieldType.String),
22 new IntermediateFieldDefinition(nameof(XmlConfigSymbolFields.Sequence), IntermediateFieldType.Number),
23 },
24 typeof(XmlConfigSymbol));
25 }
26}
27
28namespace WixToolset.Util.Symbols
29{
30 using WixToolset.Data;
31
32 public enum XmlConfigSymbolFields
33 {
34 File,
35 ElementId,
36 ElementPath,
37 VerifyPath,
38 Name,
39 Value,
40 Flags,
41 ComponentRef,
42 Sequence,
43 }
44
45 public class XmlConfigSymbol : IntermediateSymbol
46 {
47 public XmlConfigSymbol() : base(UtilSymbolDefinitions.XmlConfig, null, null)
48 {
49 }
50
51 public XmlConfigSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.XmlConfig, sourceLineNumber, id)
52 {
53 }
54
55 public IntermediateField this[XmlConfigSymbolFields index] => this.Fields[(int)index];
56
57 public string File
58 {
59 get => this.Fields[(int)XmlConfigSymbolFields.File].AsString();
60 set => this.Set((int)XmlConfigSymbolFields.File, value);
61 }
62
63 public string ElementId
64 {
65 get => this.Fields[(int)XmlConfigSymbolFields.ElementId].AsString();
66 set => this.Set((int)XmlConfigSymbolFields.ElementId, value);
67 }
68
69 public string ElementPath
70 {
71 get => this.Fields[(int)XmlConfigSymbolFields.ElementPath].AsString();
72 set => this.Set((int)XmlConfigSymbolFields.ElementPath, value);
73 }
74
75 public string VerifyPath
76 {
77 get => this.Fields[(int)XmlConfigSymbolFields.VerifyPath].AsString();
78 set => this.Set((int)XmlConfigSymbolFields.VerifyPath, value);
79 }
80
81 public string Name
82 {
83 get => this.Fields[(int)XmlConfigSymbolFields.Name].AsString();
84 set => this.Set((int)XmlConfigSymbolFields.Name, value);
85 }
86
87 public string Value
88 {
89 get => this.Fields[(int)XmlConfigSymbolFields.Value].AsString();
90 set => this.Set((int)XmlConfigSymbolFields.Value, value);
91 }
92
93 public int Flags
94 {
95 get => this.Fields[(int)XmlConfigSymbolFields.Flags].AsNumber();
96 set => this.Set((int)XmlConfigSymbolFields.Flags, value);
97 }
98
99 public string ComponentRef
100 {
101 get => this.Fields[(int)XmlConfigSymbolFields.ComponentRef].AsString();
102 set => this.Set((int)XmlConfigSymbolFields.ComponentRef, value);
103 }
104
105 public int? Sequence
106 {
107 get => this.Fields[(int)XmlConfigSymbolFields.Sequence].AsNullableNumber();
108 set => this.Set((int)XmlConfigSymbolFields.Sequence, value);
109 }
110 }
111} \ No newline at end of file
diff --git a/src/ext/Util/wixext/Symbols/XmlFileSymbol.cs b/src/ext/Util/wixext/Symbols/XmlFileSymbol.cs
new file mode 100644
index 00000000..7d5d991b
--- /dev/null
+++ b/src/ext/Util/wixext/Symbols/XmlFileSymbol.cs
@@ -0,0 +1,95 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Util.Symbols;
7
8 public static partial class UtilSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition XmlFile = new IntermediateSymbolDefinition(
11 UtilSymbolDefinitionType.XmlFile.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.File), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.ElementPath), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Name), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Value), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Flags), IntermediateFieldType.Number),
19 new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.ComponentRef), IntermediateFieldType.String),
20 new IntermediateFieldDefinition(nameof(XmlFileSymbolFields.Sequence), IntermediateFieldType.Number),
21 },
22 typeof(XmlFileSymbol));
23 }
24}
25
26namespace WixToolset.Util.Symbols
27{
28 using WixToolset.Data;
29
30 public enum XmlFileSymbolFields
31 {
32 File,
33 ElementPath,
34 Name,
35 Value,
36 Flags,
37 ComponentRef,
38 Sequence,
39 }
40
41 public class XmlFileSymbol : IntermediateSymbol
42 {
43 public XmlFileSymbol() : base(UtilSymbolDefinitions.XmlFile, null, null)
44 {
45 }
46
47 public XmlFileSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilSymbolDefinitions.XmlFile, sourceLineNumber, id)
48 {
49 }
50
51 public IntermediateField this[XmlFileSymbolFields index] => this.Fields[(int)index];
52
53 public string File
54 {
55 get => this.Fields[(int)XmlFileSymbolFields.File].AsString();
56 set => this.Set((int)XmlFileSymbolFields.File, value);
57 }
58
59 public string ElementPath
60 {
61 get => this.Fields[(int)XmlFileSymbolFields.ElementPath].AsString();
62 set => this.Set((int)XmlFileSymbolFields.ElementPath, value);
63 }
64
65 public string Name
66 {
67 get => this.Fields[(int)XmlFileSymbolFields.Name].AsString();
68 set => this.Set((int)XmlFileSymbolFields.Name, value);
69 }
70
71 public string Value
72 {
73 get => this.Fields[(int)XmlFileSymbolFields.Value].AsString();
74 set => this.Set((int)XmlFileSymbolFields.Value, value);
75 }
76
77 public int Flags
78 {
79 get => this.Fields[(int)XmlFileSymbolFields.Flags].AsNumber();
80 set => this.Set((int)XmlFileSymbolFields.Flags, value);
81 }
82
83 public string ComponentRef
84 {
85 get => this.Fields[(int)XmlFileSymbolFields.ComponentRef].AsString();
86 set => this.Set((int)XmlFileSymbolFields.ComponentRef, value);
87 }
88
89 public int? Sequence
90 {
91 get => this.Fields[(int)XmlFileSymbolFields.Sequence].AsNullableNumber();
92 set => this.Set((int)XmlFileSymbolFields.Sequence, value);
93 }
94 }
95} \ No newline at end of file
diff --git a/src/ext/Util/wixext/UtilCompiler.cs b/src/ext/Util/wixext/UtilCompiler.cs
new file mode 100644
index 00000000..45079150
--- /dev/null
+++ b/src/ext/Util/wixext/UtilCompiler.cs
@@ -0,0 +1,3889 @@
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.Util
4{
5 using System;
6 using System.Collections;
7 using System.Collections.Generic;
8 using System.Globalization;
9 using System.Linq;
10 using System.Text;
11 using System.Text.RegularExpressions;
12 using System.Xml.Linq;
13 using WixToolset.Data;
14 using WixToolset.Data.Symbols;
15 using WixToolset.Extensibility;
16 using WixToolset.Extensibility.Data;
17 using WixToolset.Util.Symbols;
18
19 /// <summary>
20 /// The compiler for the WiX Toolset Utility Extension.
21 /// </summary>
22 public sealed class UtilCompiler : BaseCompilerExtension
23 {
24 // user creation attributes definitions (from sca.h)
25 internal const int UserDontExpirePasswrd = 0x00000001;
26 internal const int UserPasswdCantChange = 0x00000002;
27 internal const int UserPasswdChangeReqdOnLogin = 0x00000004;
28 internal const int UserDisableAccount = 0x00000008;
29 internal const int UserFailIfExists = 0x00000010;
30 internal const int UserUpdateIfExists = 0x00000020;
31 internal const int UserLogonAsService = 0x00000040;
32 internal const int UserLogonAsBatchJob = 0x00000080;
33
34 internal const int UserDontRemoveOnUninstall = 0x00000100;
35 internal const int UserDontCreateUser = 0x00000200;
36 internal const int UserNonVital = 0x00000400;
37
38 private static readonly Regex FindPropertyBrackets = new Regex(@"\[(?!\\|\])|(?<!\[\\\]|\[\\|\\\[)\]", RegexOptions.ExplicitCapture | RegexOptions.Compiled);
39
40 public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/util";
41
42 /// <summary>
43 /// Types of Internet shortcuts.
44 /// </summary>
45 public enum InternetShortcutType
46 {
47 /// <summary>Create a .lnk file.</summary>
48 Link = 0,
49
50 /// <summary>Create a .url file.</summary>
51 Url,
52 }
53
54 /// <summary>
55 /// Types of permission setting methods.
56 /// </summary>
57 private enum PermissionType
58 {
59 /// <summary>LockPermissions (normal) type permission setting.</summary>
60 LockPermissions,
61
62 /// <summary>FileSharePermissions type permission setting.</summary>
63 FileSharePermissions,
64
65 /// <summary>SecureObjects type permission setting.</summary>
66 SecureObjects,
67 }
68
69 /// <summary>
70 /// Processes an element for the Compiler.
71 /// </summary>
72 /// <param name="parentElement">Parent element of element to process.</param>
73 /// <param name="element">Element to process.</param>
74 /// <param name="context">Extra information about the context in which this element is being parsed.</param>
75 public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
76 {
77 this.ParsePossibleKeyPathElement(intermediate, section, parentElement, element, context);
78 }
79
80 /// <summary>
81 /// Processes an element for the Compiler.
82 /// </summary>
83 /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
84 /// <param name="parentElement">Parent element of element to process.</param>
85 /// <param name="element">Element to process.</param>
86 /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
87 public override IComponentKeyPath ParsePossibleKeyPathElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
88 {
89 IComponentKeyPath possibleKeyPath = null;
90
91 switch (parentElement.Name.LocalName)
92 {
93 case "CreateFolder":
94 var createFolderId = context["DirectoryId"];
95 var createFolderComponentId = context["ComponentId"];
96
97 // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown
98 var createFolderWin64 = Boolean.Parse(context["Win64"]);
99
100 switch (element.Name.LocalName)
101 {
102 case "PermissionEx":
103 this.ParsePermissionExElement(intermediate, section, element, createFolderId, createFolderComponentId, createFolderWin64, "CreateFolder");
104 break;
105 default:
106 this.ParseHelper.UnexpectedElement(parentElement, element);
107 break;
108 }
109 break;
110 case "Component":
111 var componentId = context["ComponentId"];
112 var directoryId = context["DirectoryId"];
113 var componentWin64 = Boolean.Parse(context["Win64"]);
114
115 switch (element.Name.LocalName)
116 {
117 case "EventSource":
118 possibleKeyPath = this.ParseEventSourceElement(intermediate, section, element, componentId);
119 break;
120 case "FileShare":
121 this.ParseFileShareElement(intermediate, section, element, componentId, directoryId);
122 break;
123 case "InternetShortcut":
124 this.ParseInternetShortcutElement(intermediate, section, element, componentId, directoryId);
125 break;
126 case "PerformanceCategory":
127 this.ParsePerformanceCategoryElement(intermediate, section, element, componentId);
128 break;
129 case "RemoveFolderEx":
130 this.ParseRemoveFolderExElement(intermediate, section, element, componentId);
131 break;
132 case "RemoveRegistryKey":
133 this.ParseRemoveRegistryKeyExElement(intermediate, section, element, componentId);
134 break;
135 case "RestartResource":
136 this.ParseRestartResourceElement(intermediate, section, element, componentId);
137 break;
138 case "ServiceConfig":
139 this.ParseServiceConfigElement(intermediate, section, element, componentId, "Component", null);
140 break;
141 case "TouchFile":
142 this.ParseTouchFileElement(intermediate, section, element, componentId, componentWin64);
143 break;
144 case "User":
145 this.ParseUserElement(intermediate, section, element, componentId);
146 break;
147 case "XmlFile":
148 this.ParseXmlFileElement(intermediate, section, element, componentId);
149 break;
150 case "XmlConfig":
151 this.ParseXmlConfigElement(intermediate, section, element, componentId, false);
152 break;
153 default:
154 this.ParseHelper.UnexpectedElement(parentElement, element);
155 break;
156 }
157 break;
158 case "File":
159 var fileId = context["FileId"];
160 var fileComponentId = context["ComponentId"];
161
162 // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown
163 var fileWin64 = Boolean.Parse(context["Win64"]);
164
165 switch (element.Name.LocalName)
166 {
167 case "PerfCounter":
168 this.ParsePerfCounterElement(intermediate, section, element, fileComponentId, fileId);
169 break;
170 case "PermissionEx":
171 this.ParsePermissionExElement(intermediate, section, element, fileId, fileComponentId, fileWin64, "File");
172 break;
173 case "PerfCounterManifest":
174 this.ParsePerfCounterManifestElement(intermediate, section, element, fileComponentId, fileId);
175 break;
176 case "EventManifest":
177 this.ParseEventManifestElement(intermediate, section, element, fileComponentId, fileId);
178 break;
179 case "FormatFile":
180 this.ParseFormatFileElement(intermediate, section, element, fileId, fileWin64);
181 break;
182 default:
183 this.ParseHelper.UnexpectedElement(parentElement, element);
184 break;
185 }
186 break;
187 case "Bundle":
188 case "Fragment":
189 case "Module":
190 case "Package":
191 switch (element.Name.LocalName)
192 {
193 case "CloseApplication":
194 this.ParseCloseApplicationElement(intermediate, section, element);
195 break;
196 case "Group":
197 this.ParseGroupElement(intermediate, section, element, null);
198 break;
199 case "RestartResource":
200 // Currently not supported for Bundles.
201 if (parentElement.Name.LocalName != "Bundle")
202 {
203 this.ParseRestartResourceElement(intermediate, section, element, null);
204 }
205 else
206 {
207 this.ParseHelper.UnexpectedElement(parentElement, element);
208 }
209 break;
210 case "User":
211 this.ParseUserElement(intermediate, section, element, null);
212 break;
213 case "BroadcastEnvironmentChange":
214 case "BroadcastSettingChange":
215 case "CheckRebootRequired":
216 case "ExitEarlyWithSuccess":
217 case "FailWhenDeferred":
218 case "QueryWindowsDirectories":
219 case "QueryWindowsDriverInfo":
220 case "QueryWindowsSuiteInfo":
221 case "QueryWindowsWellKnownSIDs":
222 case "WaitForEvent":
223 case "WaitForEventDeferred":
224 this.AddCustomActionReference(intermediate, section, element, parentElement);
225 break;
226 case "ComponentSearch":
227 case "ComponentSearchRef":
228 case "DirectorySearch":
229 case "DirectorySearchRef":
230 case "FileSearch":
231 case "FileSearchRef":
232 case "ProductSearch":
233 case "ProductSearchRef":
234 case "RegistrySearch":
235 case "RegistrySearchRef":
236 case "WindowsFeatureSearch":
237 case "WindowsFeatureSearchRef":
238 // These will eventually be supported under Module/Product, but are not yet.
239 if (parentElement.Name.LocalName == "Bundle" || parentElement.Name.LocalName == "Fragment")
240 {
241 // TODO: When these are supported by all section types, move
242 // these out of the nested switch and back into the surrounding one.
243 switch (element.Name.LocalName)
244 {
245 case "ComponentSearch":
246 this.ParseComponentSearchElement(intermediate, section, element);
247 break;
248 case "ComponentSearchRef":
249 this.ParseComponentSearchRefElement(intermediate, section, element);
250 break;
251 case "DirectorySearch":
252 this.ParseDirectorySearchElement(intermediate, section, element);
253 break;
254 case "DirectorySearchRef":
255 this.ParseWixSearchRefElement(intermediate, section, element);
256 break;
257 case "FileSearch":
258 this.ParseFileSearchElement(intermediate, section, element);
259 break;
260 case "FileSearchRef":
261 this.ParseWixSearchRefElement(intermediate, section, element);
262 break;
263 case "ProductSearch":
264 this.ParseProductSearchElement(intermediate, section, element);
265 break;
266 case "ProductSearchRef":
267 this.ParseWixSearchRefElement(intermediate, section, element);
268 break;
269 case "RegistrySearch":
270 this.ParseRegistrySearchElement(intermediate, section, element);
271 break;
272 case "RegistrySearchRef":
273 this.ParseWixSearchRefElement(intermediate, section, element);
274 break;
275 case "WindowsFeatureSearch":
276 this.ParseWindowsFeatureSearchElement(intermediate, section, element);
277 break;
278 case "WindowsFeatureSearchRef":
279 this.ParseWindowsFeatureSearchRefElement(intermediate, section, element);
280 break;
281 }
282 }
283 else
284 {
285 this.ParseHelper.UnexpectedElement(parentElement, element);
286 }
287 break;
288 default:
289 this.ParseHelper.UnexpectedElement(parentElement, element);
290 break;
291 }
292 break;
293 case "Registry":
294 case "RegistryKey":
295 case "RegistryValue":
296 var registryId = context["RegistryId"];
297 var registryComponentId = context["ComponentId"];
298
299 // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown
300 var registryWin64 = Boolean.Parse(context["Win64"]);
301
302 switch (element.Name.LocalName)
303 {
304 case "PermissionEx":
305 this.ParsePermissionExElement(intermediate, section, element, registryId, registryComponentId, registryWin64, "Registry");
306 break;
307 default:
308 this.ParseHelper.UnexpectedElement(parentElement, element);
309 break;
310 }
311 break;
312 case "ServiceInstall":
313 var serviceInstallId = context["ServiceInstallId"];
314 var serviceInstallName = context["ServiceInstallName"];
315 var serviceInstallComponentId = context["ServiceInstallComponentId"];
316
317 // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown
318 var serviceInstallWin64 = Boolean.Parse(context["Win64"]);
319
320 switch (element.Name.LocalName)
321 {
322 case "PermissionEx":
323 this.ParsePermissionExElement(intermediate, section, element, serviceInstallId, serviceInstallComponentId, serviceInstallWin64, "ServiceInstall");
324 break;
325 case "ServiceConfig":
326 this.ParseServiceConfigElement(intermediate, section, element, serviceInstallComponentId, "ServiceInstall", serviceInstallName);
327 break;
328 default:
329 this.ParseHelper.UnexpectedElement(parentElement, element);
330 break;
331 }
332 break;
333 case "UI":
334 switch (element.Name.LocalName)
335 {
336 case "BroadcastEnvironmentChange":
337 case "BroadcastSettingChange":
338 case "CheckRebootRequired":
339 case "ExitEarlyWithSuccess":
340 case "FailWhenDeferred":
341 case "QueryWindowsDirectories":
342 case "QueryWindowsDriverInfo":
343 case "QueryWindowsSuiteInfo":
344 case "QueryWindowsWellKnownSIDs":
345 case "WaitForEvent":
346 case "WaitForEventDeferred":
347 this.AddCustomActionReference(intermediate, section, element, parentElement);
348 break;
349 }
350 break;
351 default:
352 this.ParseHelper.UnexpectedElement(parentElement, element);
353 break;
354 }
355
356 return possibleKeyPath;
357 }
358
359 private void AddCustomActionReference(Intermediate intermediate, IntermediateSection section, XElement element, XElement parentElement)
360 {
361 // These elements are not supported for bundles.
362 if (parentElement.Name.LocalName == "Bundle")
363 {
364 this.ParseHelper.UnexpectedElement(parentElement, element);
365 return;
366 }
367
368 var customAction = element.Name.LocalName;
369 switch (element.Name.LocalName)
370 {
371 case "BroadcastEnvironmentChange":
372 case "BroadcastSettingChange":
373 case "CheckRebootRequired":
374 case "ExitEarlyWithSuccess":
375 case "FailWhenDeferred":
376 case "WaitForEvent":
377 case "WaitForEventDeferred":
378 //default: customAction = element.Name.LocalName;
379 break;
380 case "QueryWindowsDirectories":
381 customAction = "QueryOsDirs";
382 break;
383 case "QueryWindowsDriverInfo":
384 customAction = "QueryOsDriverInfo";
385 break;
386 case "QueryWindowsSuiteInfo":
387 customAction = "QueryOsInfo";
388 break;
389 case "QueryWindowsWellKnownSIDs":
390 customAction = "QueryOsWellKnownSID";
391 break;
392 }
393
394 foreach (var attrib in element.Attributes())
395 {
396 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
397 {
398 // no attributes today
399 }
400 else
401 {
402 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
403 }
404 }
405
406 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
407
408 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
409
410 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4" + customAction, this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
411 }
412
413 /// <summary>
414 /// Parses the common search attributes shared across all searches.
415 /// </summary>
416 /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
417 /// <param name="attrib">Attribute to parse.</param>
418 /// <param name="id">Value of the Id attribute.</param>
419 /// <param name="variable">Value of the Variable attribute.</param>
420 /// <param name="condition">Value of the Condition attribute.</param>
421 /// <param name="after">Value of the After attribute.</param>
422 private void ParseCommonSearchAttributes(SourceLineNumber sourceLineNumbers, XAttribute attrib, ref Identifier id, ref string variable, ref string condition, ref string after)
423 {
424 switch (attrib.Name.LocalName)
425 {
426 case "Id":
427 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
428 break;
429 case "Variable":
430 variable = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
431 // TODO: handle standard bundle variables
432 break;
433 case "Condition":
434 condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
435 break;
436 case "After":
437 after = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
438 break;
439 default:
440 System.Diagnostics.Debug.Assert(false);
441 break;
442 }
443 }
444
445 /// <summary>
446 /// Parses a ComponentSearch element.
447 /// </summary>
448 /// <param name="element">Element to parse.</param>
449 private void ParseComponentSearchElement(Intermediate intermediate, IntermediateSection section, XElement element)
450 {
451 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
452 Identifier id = null;
453 string variable = null;
454 string condition = null;
455 string after = null;
456 string guid = null;
457 string productCode = null;
458 var attributes = WixComponentSearchAttributes.KeyPath;
459
460 foreach (var attrib in element.Attributes())
461 {
462 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
463 {
464 switch (attrib.Name.LocalName)
465 {
466 case "Id":
467 case "Variable":
468 case "Condition":
469 case "After":
470 this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after);
471 break;
472 case "Guid":
473 guid = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib);
474 break;
475 case "ProductCode":
476 productCode = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib);
477 break;
478 case "Result":
479 var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
480 switch (result)
481 {
482 case "directory":
483 attributes = WixComponentSearchAttributes.WantDirectory;
484 break;
485 case "keyPath":
486 attributes = WixComponentSearchAttributes.KeyPath;
487 break;
488 case "state":
489 attributes = WixComponentSearchAttributes.State;
490 break;
491 default:
492 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "directory", "keyPath", "state"));
493 break;
494 }
495 break;
496 default:
497 this.ParseHelper.UnexpectedAttribute(element, attrib);
498 break;
499 }
500 }
501 else
502 {
503 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
504 }
505 }
506
507 if (null == guid)
508 {
509 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Guid"));
510 }
511
512 if (null == id)
513 {
514 id = this.ParseHelper.CreateIdentifier("wcs", variable, condition, after, guid, productCode, attributes.ToString());
515 }
516
517 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
518
519 this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null);
520
521 if (!this.Messaging.EncounteredError)
522 {
523 section.AddSymbol(new WixComponentSearchSymbol(sourceLineNumbers, id)
524 {
525 Guid = guid,
526 ProductCode = productCode,
527 Attributes = attributes,
528 });
529 }
530 }
531
532 /// <summary>
533 /// Parses a ComponentSearchRef element
534 /// </summary>
535 /// <param name="element">Element to parse.</param>
536 private void ParseComponentSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element)
537 {
538 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
539 string refId = null;
540
541 foreach (var attrib in element.Attributes())
542 {
543 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
544 {
545 switch (attrib.Name.LocalName)
546 {
547 case "Id":
548 refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
549 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixComponentSearch, refId);
550 break;
551 default:
552 this.ParseHelper.UnexpectedAttribute(element, attrib);
553 break;
554 }
555 }
556 else
557 {
558 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
559 }
560 }
561
562 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
563 }
564
565 /// <summary>
566 /// Parses a WindowsFeatureSearch element.
567 /// </summary>
568 /// <param name="element">Element to parse.</param>
569 private void ParseWindowsFeatureSearchElement(Intermediate intermediate, IntermediateSection section, XElement element)
570 {
571 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
572 Identifier id = null;
573 string variable = null;
574 string condition = null;
575 string after = null;
576 string feature = null;
577
578 foreach (var attrib in element.Attributes())
579 {
580 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
581 {
582 switch (attrib.Name.LocalName)
583 {
584 case "Id":
585 case "Variable":
586 case "Condition":
587 case "After":
588 this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after);
589 break;
590 case "Feature":
591 feature = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
592 switch (feature)
593 {
594 case "sha2CodeSigning":
595 break;
596 default:
597 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Feature", feature, "sha2CodeSigning"));
598 break;
599 }
600 break;
601 default:
602 this.ParseHelper.UnexpectedAttribute(element, attrib);
603 break;
604 }
605 }
606 else
607 {
608 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
609 }
610 }
611
612 if (id == null)
613 {
614 id = this.ParseHelper.CreateIdentifier("wwfs", variable, condition, after);
615 }
616
617 if (feature == null)
618 {
619 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Feature"));
620 }
621
622 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
623
624 var bundleExtensionId = this.ParseHelper.CreateIdentifierValueFromPlatform("Wix4UtilBundleExtension", this.Context.Platform, BurnPlatforms.X86 | BurnPlatforms.X64 | BurnPlatforms.ARM64);
625 if (bundleExtensionId == null)
626 {
627 this.Messaging.Write(ErrorMessages.UnsupportedPlatformForElement(sourceLineNumbers, this.Context.Platform.ToString(), element.Name.LocalName));
628 }
629
630 this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, bundleExtensionId);
631
632 if (!this.Messaging.EncounteredError)
633 {
634 section.AddSymbol(new WixWindowsFeatureSearchSymbol(sourceLineNumbers, id)
635 {
636 Type = feature,
637 });
638 }
639 }
640
641 /// <summary>
642 /// Parses a WindowsFeatureSearchRef element
643 /// </summary>
644 /// <param name="element">Element to parse.</param>
645 private void ParseWindowsFeatureSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element)
646 {
647 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
648
649 foreach (var attrib in element.Attributes())
650 {
651 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
652 {
653 switch (attrib.Name.LocalName)
654 {
655 case "Id":
656 var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
657 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.WixWindowsFeatureSearch, refId);
658 break;
659 default:
660 this.ParseHelper.UnexpectedAttribute(element, attrib);
661 break;
662 }
663 }
664 else
665 {
666 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
667 }
668 }
669
670 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
671 }
672
673 /// <summary>
674 /// Parses an event source element.
675 /// </summary>
676 /// <param name="element">Element to parse.</param>
677 /// <param name="componentId">Identifier of parent component.</param>
678 private IComponentKeyPath ParseEventSourceElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
679 {
680 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
681 string sourceName = null;
682 string logName = null;
683 string categoryMessageFile = null;
684 var categoryCount = CompilerConstants.IntegerNotSet;
685 string eventMessageFile = null;
686 string parameterMessageFile = null;
687 int typesSupported = 0;
688 var isKeyPath = false;
689
690 foreach (var attrib in element.Attributes())
691 {
692 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
693 {
694 switch (attrib.Name.LocalName)
695 {
696 case "CategoryCount":
697 categoryCount = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue);
698 break;
699 case "CategoryMessageFile":
700 categoryMessageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
701 break;
702 case "EventMessageFile":
703 eventMessageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
704 break;
705 case "KeyPath":
706 isKeyPath = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
707 break;
708 case "Log":
709 logName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
710 if ("Security" == logName)
711 {
712 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, logName, "Application", "System", "<customEventLog>"));
713 }
714 break;
715 case "Name":
716 sourceName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
717 break;
718 case "ParameterMessageFile":
719 parameterMessageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
720 break;
721 case "SupportsErrors":
722 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
723 {
724 typesSupported |= 0x01; // EVENTLOG_ERROR_TYPE
725 }
726 break;
727 case "SupportsFailureAudits":
728 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
729 {
730 typesSupported |= 0x10; // EVENTLOG_AUDIT_FAILURE
731 }
732 break;
733 case "SupportsInformationals":
734 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
735 {
736 typesSupported |= 0x04; // EVENTLOG_INFORMATION_TYPE
737 }
738 break;
739 case "SupportsSuccessAudits":
740 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
741 {
742 typesSupported |= 0x08; // EVENTLOG_AUDIT_SUCCESS
743 }
744 break;
745 case "SupportsWarnings":
746 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
747 {
748 typesSupported |= 0x02; // EVENTLOG_WARNING_TYPE
749 }
750 break;
751 default:
752 this.ParseHelper.UnexpectedAttribute(element, attrib);
753 break;
754 }
755 }
756 else
757 {
758 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
759 }
760 }
761
762 if (null == sourceName)
763 {
764 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
765 }
766
767 if (null == logName)
768 {
769 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "EventLog"));
770 }
771
772 if (null == eventMessageFile)
773 {
774 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "EventMessageFile"));
775 }
776
777 if (null == categoryMessageFile && 0 < categoryCount)
778 {
779 this.Messaging.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, element.Name.LocalName, "CategoryCount", "CategoryMessageFile"));
780 }
781
782 if (null != categoryMessageFile && CompilerConstants.IntegerNotSet == categoryCount)
783 {
784 this.Messaging.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, element.Name.LocalName, "CategoryMessageFile", "CategoryCount"));
785 }
786
787 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
788
789 string eventSourceKey = $@"SYSTEM\CurrentControlSet\Services\EventLog\{logName}\{sourceName}";
790 var id = this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "EventMessageFile", String.Concat("#%", eventMessageFile), componentId, false);
791
792 if (null != categoryMessageFile)
793 {
794 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "CategoryMessageFile", String.Concat("#%", categoryMessageFile), componentId, false);
795 }
796
797 if (CompilerConstants.IntegerNotSet != categoryCount)
798 {
799 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "CategoryCount", String.Concat("#", categoryCount), componentId, false);
800 }
801
802 if (null != parameterMessageFile)
803 {
804 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "ParameterMessageFile", String.Concat("#%", parameterMessageFile), componentId, false);
805 }
806
807 if (0 != typesSupported)
808 {
809 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, eventSourceKey, "TypesSupported", String.Concat("#", typesSupported), componentId, false);
810 }
811
812 var componentKeyPath = this.CreateComponentKeyPath();
813 componentKeyPath.Id = id.Id;
814 componentKeyPath.Explicit = isKeyPath;
815 componentKeyPath.Type = PossibleKeyPathType.Registry;
816 return componentKeyPath;
817 }
818
819 /// <summary>
820 /// Parses a close application element.
821 /// </summary>
822 /// <param name="element">Element to parse.</param>
823 private void ParseCloseApplicationElement(Intermediate intermediate, IntermediateSection section, XElement element)
824 {
825 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
826 string condition = null;
827 string description = null;
828 string target = null;
829 string property = null;
830 Identifier id = null;
831 int attributes = 2; // default to CLOSEAPP_ATTRIBUTE_REBOOTPROMPT enabled
832 var sequence = CompilerConstants.IntegerNotSet;
833 var terminateExitCode = CompilerConstants.IntegerNotSet;
834 var timeout = CompilerConstants.IntegerNotSet;
835
836 foreach (var attrib in element.Attributes())
837 {
838 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
839 {
840 switch (attrib.Name.LocalName)
841 {
842 case "Id":
843 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
844 break;
845 case "Condition":
846 condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
847 break;
848 case "Description":
849 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
850 break;
851 case "Property":
852 property = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
853 break;
854 case "Sequence":
855 sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue);
856 break;
857 case "Timeout":
858 timeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue);
859 break;
860 case "Target":
861 target = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
862 break;
863 case "CloseMessage":
864 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
865 {
866 attributes |= 1; // CLOSEAPP_ATTRIBUTE_CLOSEMESSAGE
867 }
868 else
869 {
870 attributes &= ~1; // CLOSEAPP_ATTRIBUTE_CLOSEMESSAGE
871 }
872 break;
873 case "EndSessionMessage":
874 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
875 {
876 attributes |= 8; // CLOSEAPP_ATTRIBUTE_ENDSESSIONMESSAGE
877 }
878 else
879 {
880 attributes &= ~8; // CLOSEAPP_ATTRIBUTE_ENDSESSIONMESSAGE
881 }
882 break;
883 case "PromptToContinue":
884 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
885 {
886 attributes |= 0x40; // CLOSEAPP_ATTRIBUTE_PROMPTTOCONTINUE
887 }
888 else
889 {
890 attributes &= ~0x40; // CLOSEAPP_ATTRIBUTE_PROMPTTOCONTINUE
891 }
892 break;
893 case "RebootPrompt":
894 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
895 {
896 attributes |= 2; // CLOSEAPP_ATTRIBUTE_REBOOTPROMPT
897 }
898 else
899 {
900 attributes &= ~2; // CLOSEAPP_ATTRIBUTE_REBOOTPROMPT
901 }
902 break;
903 case "ElevatedCloseMessage":
904 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
905 {
906 attributes |= 4; // CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE
907 }
908 else
909 {
910 attributes &= ~4; // CLOSEAPP_ATTRIBUTE_ELEVATEDCLOSEMESSAGE
911 }
912 break;
913 case "ElevatedEndSessionMessage":
914 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
915 {
916 attributes |= 0x10; // CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE
917 }
918 else
919 {
920 attributes &= ~0x10; // CLOSEAPP_ATTRIBUTE_ELEVATEDENDSESSIONMESSAGE
921 }
922 break;
923 case "TerminateProcess":
924 terminateExitCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue);
925 attributes |= 0x20; // CLOSEAPP_ATTRIBUTE_TERMINATEPROCESS
926 break;
927 default:
928 this.ParseHelper.UnexpectedAttribute(element, attrib);
929 break;
930 }
931 }
932 else
933 {
934 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
935 }
936 }
937
938 if (null == target)
939 {
940 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Target"));
941 }
942 else if (null == id)
943 {
944 id = this.ParseHelper.CreateIdentifier("ca", target);
945 }
946
947 if (String.IsNullOrEmpty(description) && 0x40 == (attributes & 0x40))
948 {
949 this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithoutOtherAttribute(sourceLineNumbers, element.Name.LocalName, "PromptToContinue", "yes", "Description"));
950 }
951
952 if (0x22 == (attributes & 0x22))
953 {
954 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "TerminateProcess", "RebootPrompt", "yes"));
955 }
956
957 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
958
959 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4CloseApplications", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
960
961 if (!this.Messaging.EncounteredError)
962 {
963 var symbol = section.AddSymbol(new WixCloseApplicationSymbol(sourceLineNumbers, id)
964 {
965 Target = target,
966 Description = description,
967 Condition = condition,
968 Attributes = attributes,
969 Property = property,
970 });
971 if (CompilerConstants.IntegerNotSet != sequence)
972 {
973 symbol.Sequence = sequence;
974 }
975 if (CompilerConstants.IntegerNotSet != terminateExitCode)
976 {
977 symbol.TerminateExitCode = terminateExitCode;
978 }
979 if (CompilerConstants.IntegerNotSet != timeout)
980 {
981 symbol.Timeout = timeout * 1000; // make the timeout milliseconds in the table.
982 }
983 }
984 }
985
986 /// <summary>
987 /// Parses a DirectorySearch element.
988 /// </summary>
989 /// <param name="element">Element to parse.</param>
990 private void ParseDirectorySearchElement(Intermediate intermediate, IntermediateSection section, XElement element)
991 {
992 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
993 Identifier id = null;
994 string variable = null;
995 string condition = null;
996 string after = null;
997 string path = null;
998 var attributes = WixFileSearchAttributes.IsDirectory;
999
1000 foreach (var attrib in element.Attributes())
1001 {
1002 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1003 {
1004 switch (attrib.Name.LocalName)
1005 {
1006 case "Id":
1007 case "Variable":
1008 case "Condition":
1009 case "After":
1010 this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after);
1011 break;
1012 case "Path":
1013 path = this.ParseHelper.GetAttributeLongFilename(sourceLineNumbers, attrib, false, true);
1014 break;
1015 case "Result":
1016 var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1017 switch (result)
1018 {
1019 case "exists":
1020 attributes |= WixFileSearchAttributes.WantExists;
1021 break;
1022 default:
1023 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "exists"));
1024 break;
1025 }
1026 break;
1027 default:
1028 this.ParseHelper.UnexpectedAttribute(element, attrib);
1029 break;
1030 }
1031 }
1032 else
1033 {
1034 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1035 }
1036 }
1037
1038 if (null == path)
1039 {
1040 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path"));
1041 }
1042
1043 if (null == id)
1044 {
1045 id = this.ParseHelper.CreateIdentifier("wds", variable, condition, after, path, attributes.ToString());
1046 }
1047
1048 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
1049
1050 this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null);
1051
1052 if (!this.Messaging.EncounteredError)
1053 {
1054 this.CreateWixFileSearchRow(section, sourceLineNumbers, id, path, attributes);
1055 }
1056 }
1057
1058 /// <summary>
1059 /// Parses a DirectorySearchRef, FileSearchRef, ProductSearchRef, and RegistrySearchRef elements
1060 /// </summary>
1061 /// <param name="node">Element to parse.</param>
1062 private void ParseWixSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement node)
1063 {
1064 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node);
1065
1066 foreach (XAttribute attrib in node.Attributes())
1067 {
1068 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1069 {
1070 switch (attrib.Name.LocalName)
1071 {
1072 case "Id":
1073 var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1074 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixSearch, refId);
1075 break;
1076 default:
1077 this.ParseHelper.UnexpectedAttribute(node, attrib);
1078 break;
1079 }
1080 }
1081 else
1082 {
1083 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib);
1084 }
1085 }
1086
1087 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node);
1088 }
1089
1090 /// <summary>
1091 /// Parses a FileSearch element.
1092 /// </summary>
1093 /// <param name="node">Element to parse.</param>
1094 private void ParseFileSearchElement(Intermediate intermediate, IntermediateSection section, XElement node)
1095 {
1096 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node);
1097 Identifier id = null;
1098 string variable = null;
1099 string condition = null;
1100 string after = null;
1101 string path = null;
1102 var attributes = WixFileSearchAttributes.Default;
1103
1104 foreach (var attrib in node.Attributes())
1105 {
1106 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1107 {
1108 switch (attrib.Name.LocalName)
1109 {
1110 case "Id":
1111 case "Variable":
1112 case "Condition":
1113 case "After":
1114 this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after);
1115 break;
1116 case "Path":
1117 path = this.ParseHelper.GetAttributeLongFilename(sourceLineNumbers, attrib, false, true);
1118 break;
1119 case "Result":
1120 string result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1121 switch (result)
1122 {
1123 case "exists":
1124 attributes |= WixFileSearchAttributes.WantExists;
1125 break;
1126 case "version":
1127 attributes |= WixFileSearchAttributes.WantVersion;
1128 break;
1129 default:
1130 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "exists", "version"));
1131 break;
1132 }
1133 break;
1134 default:
1135 this.ParseHelper.UnexpectedAttribute(node, attrib);
1136 break;
1137 }
1138 }
1139 else
1140 {
1141 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib);
1142 }
1143 }
1144
1145 if (null == path)
1146 {
1147 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Path"));
1148 }
1149
1150 if (null == id)
1151 {
1152 id = this.ParseHelper.CreateIdentifier("wfs", variable, condition, after, path, attributes.ToString());
1153 }
1154
1155 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node);
1156
1157 this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, node.Name.LocalName, id, variable, condition, after, null);
1158
1159 if (!this.Messaging.EncounteredError)
1160 {
1161 this.CreateWixFileSearchRow(section, sourceLineNumbers, id, path, attributes);
1162 }
1163 }
1164
1165 /// <summary>
1166 /// Creates a row in the WixFileSearch table.
1167 /// </summary>
1168 /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
1169 /// <param name="id">Identifier of the search (key into the WixSearch table)</param>
1170 /// <param name="path">File/directory path to search for.</param>
1171 /// <param name="attributes"></param>
1172 private void CreateWixFileSearchRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string path, WixFileSearchAttributes attributes)
1173 {
1174 section.AddSymbol(new WixFileSearchSymbol(sourceLineNumbers, id)
1175 {
1176 Path = path,
1177 Attributes = attributes,
1178 });
1179 }
1180
1181 /// <summary>
1182 /// Parses a file share element.
1183 /// </summary>
1184 /// <param name="element">Element to parse.</param>
1185 /// <param name="componentId">Identifier of parent component.</param>
1186 /// <param name="directoryId">Identifier of referred to directory.</param>
1187 private void ParseFileShareElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string directoryId)
1188 {
1189 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1190 string description = null;
1191 string name = null;
1192 Identifier id = null;
1193
1194 foreach (var attrib in element.Attributes())
1195 {
1196 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1197 {
1198 switch (attrib.Name.LocalName)
1199 {
1200 case "Id":
1201 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
1202 break;
1203 case "Name":
1204 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1205 break;
1206 case "Description":
1207 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1208 break;
1209 default:
1210 this.ParseHelper.UnexpectedAttribute(element, attrib);
1211 break;
1212 }
1213 }
1214 else
1215 {
1216 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1217 }
1218 }
1219
1220 if (null == id)
1221 {
1222 id = this.ParseHelper.CreateIdentifier("ufs", componentId, name);
1223 }
1224
1225 if (null == name)
1226 {
1227 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
1228 }
1229
1230 if (!element.Elements().Any())
1231 {
1232 this.Messaging.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, element.Name.LocalName, "FileSharePermission"));
1233 }
1234
1235 foreach (var child in element.Elements())
1236 {
1237 if (this.Namespace == child.Name.Namespace)
1238 {
1239 switch (child.Name.LocalName)
1240 {
1241 case "FileSharePermission":
1242 this.ParseFileSharePermissionElement(intermediate, section, child, id);
1243 break;
1244 default:
1245 this.ParseHelper.UnexpectedElement(element, child);
1246 break;
1247 }
1248 }
1249 else
1250 {
1251 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
1252 }
1253 }
1254
1255 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureSmbInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
1256 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureSmbUninstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
1257
1258 if (!this.Messaging.EncounteredError)
1259 {
1260 section.AddSymbol(new FileShareSymbol(sourceLineNumbers, id)
1261 {
1262 ShareName = name,
1263 ComponentRef = componentId,
1264 Description = description,
1265 DirectoryRef = directoryId,
1266 });
1267 }
1268 }
1269
1270 /// <summary>
1271 /// Parses a FileSharePermission element.
1272 /// </summary>
1273 /// <param name="element">Element to parse.</param>
1274 /// <param name="fileShareId">The identifier of the parent FileShare element.</param>
1275 private void ParseFileSharePermissionElement(Intermediate intermediate, IntermediateSection section, XElement element, Identifier fileShareId)
1276 {
1277 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1278 var bits = new BitArray(32);
1279 string user = null;
1280
1281 foreach (var attrib in element.Attributes())
1282 {
1283 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1284 {
1285 switch (attrib.Name.LocalName)
1286 {
1287 case "User":
1288 user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1289 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.User, user);
1290 break;
1291 default:
1292 var attribValue = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1293 if (!this.TrySetBitFromName(UtilConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16))
1294 {
1295 if (!this.TrySetBitFromName(UtilConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28))
1296 {
1297 if (!this.TrySetBitFromName(UtilConstants.FolderPermissions, attrib.Name.LocalName, attribValue, bits, 0))
1298 {
1299 this.ParseHelper.UnexpectedAttribute(element, attrib);
1300 break;
1301 }
1302 }
1303 }
1304 break;
1305 }
1306 }
1307 else
1308 {
1309 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1310 }
1311 }
1312
1313 var permission = this.CreateIntegerFromBitArray(bits);
1314
1315 if (null == user)
1316 {
1317 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "User"));
1318 }
1319
1320 if (Int32.MinValue == permission) // just GENERIC_READ, which is MSI_NULL
1321 {
1322 this.Messaging.Write(ErrorMessages.GenericReadNotAllowed(sourceLineNumbers));
1323 }
1324
1325 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
1326
1327 if (!this.Messaging.EncounteredError)
1328 {
1329 section.AddSymbol(new FileSharePermissionsSymbol(sourceLineNumbers)
1330 {
1331 FileShareRef = fileShareId.Id,
1332 UserRef = user,
1333 Permissions = permission,
1334 });
1335 }
1336 }
1337
1338 /// <summary>
1339 /// Parses a group element.
1340 /// </summary>
1341 /// <param name="element">Node to be parsed.</param>
1342 /// <param name="componentId">Component Id of the parent component of this element.</param>
1343 private void ParseGroupElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
1344 {
1345 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1346 Identifier id = null;
1347 string domain = null;
1348 string name = null;
1349
1350 foreach (var attrib in element.Attributes())
1351 {
1352 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1353 {
1354 switch (attrib.Name.LocalName)
1355 {
1356 case "Id":
1357 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
1358 break;
1359 case "Name":
1360 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1361 break;
1362 case "Domain":
1363 domain = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1364 break;
1365 default:
1366 this.ParseHelper.UnexpectedAttribute(element, attrib);
1367 break;
1368 }
1369 }
1370 else
1371 {
1372 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1373 }
1374 }
1375
1376 if (null == id)
1377 {
1378 id = this.ParseHelper.CreateIdentifier("ugr", componentId, domain, name);
1379 }
1380
1381 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
1382
1383 if (!this.Messaging.EncounteredError)
1384 {
1385 section.AddSymbol(new GroupSymbol(sourceLineNumbers, id)
1386 {
1387 ComponentRef = componentId,
1388 Name = name,
1389 Domain = domain,
1390 });
1391 }
1392 }
1393
1394 /// <summary>
1395 /// Parses a GroupRef element
1396 /// </summary>
1397 /// <param name="element">Element to parse.</param>
1398 /// <param name="userId">Required user id to be joined to the group.</param>
1399 private void ParseGroupRefElement(Intermediate intermediate, IntermediateSection section, XElement element, string userId)
1400 {
1401 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1402 string groupId = null;
1403
1404 foreach (var attrib in element.Attributes())
1405 {
1406 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1407 {
1408 switch (attrib.Name.LocalName)
1409 {
1410 case "Id":
1411 groupId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1412 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.Group, groupId);
1413 break;
1414 default:
1415 this.ParseHelper.UnexpectedAttribute(element, attrib);
1416 break;
1417 }
1418 }
1419 else
1420 {
1421 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1422 }
1423 }
1424
1425 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
1426
1427 if (!this.Messaging.EncounteredError)
1428 {
1429 section.AddSymbol(new UserGroupSymbol(sourceLineNumbers)
1430 {
1431 UserRef = userId,
1432 GroupRef = groupId,
1433 });
1434 }
1435 }
1436
1437 /// <summary>
1438 /// Parses an InternetShortcut element.
1439 /// </summary>
1440 /// <param name="element">Element to parse.</param>
1441 /// <param name="componentId">Identifier of parent component.</param>
1442 /// <param name="defaultTarget">Default directory if none is specified on the InternetShortcut element.</param>
1443 private void ParseInternetShortcutElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string defaultTarget)
1444 {
1445 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1446 Identifier id = null;
1447 string name = null;
1448 string target = null;
1449 string directoryId = null;
1450 string type = null;
1451 string iconFile = null;
1452 int iconIndex = 0;
1453
1454 foreach (var attrib in element.Attributes())
1455 {
1456 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1457 {
1458 switch (attrib.Name.LocalName)
1459 {
1460 case "Directory":
1461 directoryId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1462 break;
1463 case "Id":
1464 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
1465 break;
1466 case "Name":
1467 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1468 break;
1469 case "Target":
1470 target = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1471 break;
1472 case "Type":
1473 type = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1474 break;
1475 case "IconFile":
1476 iconFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1477 break;
1478 case "IconIndex":
1479 iconIndex = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue);
1480 break;
1481 default:
1482 this.ParseHelper.UnexpectedAttribute(element, attrib);
1483 break;
1484 }
1485 }
1486 else
1487 {
1488 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1489 }
1490 }
1491
1492 // If there was no directoryId specified on the InternetShortcut element, default to the one on
1493 // the parent component.
1494 if (null == directoryId)
1495 {
1496 directoryId = defaultTarget;
1497 }
1498
1499 if (null == id)
1500 {
1501 id = this.ParseHelper.CreateIdentifier("uis", componentId, directoryId, name, target);
1502 }
1503
1504 // In theory this can never be the case, since InternetShortcut can only be under
1505 // a component element, and if the Directory wasn't specified the default will come
1506 // from the component. However, better safe than sorry, so here's a check to make sure
1507 // it didn't wind up being null after setting it to the defaultTarget.
1508 if (null == directoryId)
1509 {
1510 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Directory"));
1511 }
1512
1513 if (null == name)
1514 {
1515 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
1516 }
1517
1518 if (null == target)
1519 {
1520 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Target"));
1521 }
1522
1523 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
1524
1525 var shortcutType = InternetShortcutType.Link;
1526 if (String.Equals(type, "url", StringComparison.OrdinalIgnoreCase))
1527 {
1528 shortcutType = InternetShortcutType.Url;
1529 }
1530
1531 if (!this.Messaging.EncounteredError)
1532 {
1533 this.CreateWixInternetShortcut(section, sourceLineNumbers, componentId, directoryId, id, name, target, shortcutType, iconFile, iconIndex);
1534 }
1535 }
1536
1537 /// <summary>
1538 /// Creates the rows needed for WixInternetShortcut to work.
1539 /// </summary>
1540 /// <param name="core">The CompilerCore object used to create rows.</param>
1541 /// <param name="sourceLineNumbers">Source line information about the owner element.</param>
1542 /// <param name="componentId">Identifier of parent component.</param>
1543 /// <param name="directoryId">Identifier of directory containing shortcut.</param>
1544 /// <param name="id">Identifier of shortcut.</param>
1545 /// <param name="name">Name of shortcut without extension.</param>
1546 /// <param name="target">Target URL of shortcut.</param>
1547 private void CreateWixInternetShortcut(IntermediateSection section, SourceLineNumber sourceLineNumbers, string componentId, string directoryId, Identifier shortcutId, string name, string target, InternetShortcutType type, string iconFile, int iconIndex)
1548 {
1549 // add the appropriate extension based on type of shortcut
1550 name = String.Concat(name, InternetShortcutType.Url == type ? ".url" : ".lnk");
1551
1552 section.AddSymbol(new WixInternetShortcutSymbol(sourceLineNumbers, shortcutId)
1553 {
1554 ComponentRef = componentId,
1555 DirectoryRef = directoryId,
1556 Name = name,
1557 Target = target,
1558 Attributes = (int)type,
1559 IconFile = iconFile,
1560 IconIndex = iconIndex,
1561 });
1562
1563 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedInternetShortcuts", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
1564
1565 // make sure we have a CreateFolder table so that the immediate CA can add temporary rows to handle installation and uninstallation
1566 this.ParseHelper.EnsureTable(section, sourceLineNumbers, "CreateFolder");
1567
1568 // use built-in MSI functionality to remove the shortcuts rather than doing so via CA
1569 section.AddSymbol(new RemoveFileSymbol(sourceLineNumbers, shortcutId)
1570 {
1571 ComponentRef = componentId,
1572 DirPropertyRef = directoryId,
1573 OnUninstall = true,
1574 FileName = name,
1575 });
1576 }
1577
1578 /// <summary>
1579 /// Parses a performance category element.
1580 /// </summary>
1581 /// <param name="element">Element to parse.</param>
1582 /// <param name="componentId">Identifier of parent component.</param>
1583 private void ParsePerformanceCategoryElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
1584 {
1585 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1586 Identifier id = null;
1587 string name = null;
1588 string help = null;
1589 var multiInstance = YesNoType.No;
1590 int defaultLanguage = 0x09; // default to "english"
1591
1592 var parsedPerformanceCounters = new List<ParsedPerformanceCounter>();
1593
1594 // default to managed performance counter
1595 var library = "netfxperf.dll";
1596 var openEntryPoint = "OpenPerformanceData";
1597 var collectEntryPoint = "CollectPerformanceData";
1598 var closeEntryPoint = "ClosePerformanceData";
1599
1600 foreach (var attrib in element.Attributes())
1601 {
1602 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1603 {
1604 switch (attrib.Name.LocalName)
1605 {
1606 case "Close":
1607 closeEntryPoint = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1608 break;
1609 case "Collect":
1610 collectEntryPoint = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1611 break;
1612 case "DefaultLanguage":
1613 defaultLanguage = this.GetPerformanceCounterLanguage(sourceLineNumbers, attrib);
1614 break;
1615 case "Help":
1616 help = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1617 break;
1618 case "Id":
1619 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
1620 break;
1621 case "Library":
1622 library = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1623 break;
1624 case "MultiInstance":
1625 multiInstance = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1626 break;
1627 case "Name":
1628 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1629 break;
1630 case "Open":
1631 openEntryPoint = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1632 break;
1633 default:
1634 this.ParseHelper.UnexpectedAttribute(element, attrib);
1635 break;
1636 }
1637 }
1638 else
1639 {
1640 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1641 }
1642 }
1643
1644 if (null == id && null == name)
1645 {
1646 this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "Id", "Name"));
1647 }
1648 else if (null == id)
1649 {
1650 id = this.ParseHelper.CreateIdentifier("upc", componentId, name);
1651 }
1652 else if (null == name)
1653 {
1654 name = id.Id;
1655 }
1656
1657 // Process the child counter elements.
1658 foreach (var child in element.Elements())
1659 {
1660 if (this.Namespace == child.Name.Namespace)
1661 {
1662 switch (child.Name.LocalName)
1663 {
1664 case "PerformanceCounter":
1665 var counter = this.ParsePerformanceCounterElement(intermediate, section, child, defaultLanguage);
1666 if (null != counter)
1667 {
1668 parsedPerformanceCounters.Add(counter);
1669 }
1670 break;
1671 default:
1672 this.ParseHelper.UnexpectedElement(element, child);
1673 break;
1674 }
1675 }
1676 else
1677 {
1678 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
1679 }
1680 }
1681
1682
1683 if (!this.Messaging.EncounteredError)
1684 {
1685 // Calculate the ini and h file content.
1686 var objectName = "OBJECT_1";
1687 var objectLanguage = defaultLanguage.ToString("D3", CultureInfo.InvariantCulture);
1688
1689 var sbIniData = new StringBuilder();
1690 sbIniData.AppendFormat("[info]\r\ndrivername={0}\r\nsymbolfile=wixperf.h\r\n\r\n[objects]\r\n{1}_{2}_NAME=\r\n\r\n[languages]\r\n{2}=LANG{2}\r\n\r\n", name, objectName, objectLanguage);
1691 sbIniData.AppendFormat("[text]\r\n{0}_{1}_NAME={2}\r\n", objectName, objectLanguage, name);
1692 if (null != help)
1693 {
1694 sbIniData.AppendFormat("{0}_{1}_HELP={2}\r\n", objectName, objectLanguage, help);
1695 }
1696
1697 int symbolConstantsCounter = 0;
1698 var sbSymbolicConstants = new StringBuilder();
1699 sbSymbolicConstants.AppendFormat("#define {0} {1}\r\n", objectName, symbolConstantsCounter);
1700
1701 var sbCounterNames = new StringBuilder("[~]");
1702 var sbCounterTypes = new StringBuilder("[~]");
1703 for (int i = 0; i < parsedPerformanceCounters.Count; ++i)
1704 {
1705 var counter = parsedPerformanceCounters[i];
1706 var counterName = String.Concat("DEVICE_COUNTER_", i + 1);
1707
1708 sbIniData.AppendFormat("{0}_{1}_NAME={2}\r\n", counterName, counter.Language, counter.Name);
1709 if (null != counter.Help)
1710 {
1711 sbIniData.AppendFormat("{0}_{1}_HELP={2}\r\n", counterName, counter.Language, counter.Help);
1712 }
1713
1714 symbolConstantsCounter += 2;
1715 sbSymbolicConstants.AppendFormat("#define {0} {1}\r\n", counterName, symbolConstantsCounter);
1716
1717 sbCounterNames.Append(UtilCompiler.FindPropertyBrackets.Replace(counter.Name, this.EscapeProperties));
1718 sbCounterNames.Append("[~]");
1719 sbCounterTypes.Append(counter.Type);
1720 sbCounterTypes.Append("[~]");
1721 }
1722
1723 sbSymbolicConstants.AppendFormat("#define LAST_{0}_COUNTER_OFFSET {1}\r\n", objectName, symbolConstantsCounter);
1724
1725 // Add the calculated INI and H strings to the PerformanceCategory table.
1726 section.AddSymbol(new PerformanceCategorySymbol(sourceLineNumbers, id)
1727 {
1728 ComponentRef = componentId,
1729 Name = name,
1730 IniData = sbIniData.ToString(),
1731 ConstantData = sbSymbolicConstants.ToString(),
1732 });
1733
1734 // Set up the application's performance key.
1735 var escapedName = UtilCompiler.FindPropertyBrackets.Replace(name, this.EscapeProperties);
1736 var linkageKey = String.Format(@"SYSTEM\CurrentControlSet\Services\{0}\Linkage", escapedName);
1737 var performanceKey = String.Format(@"SYSTEM\CurrentControlSet\Services\{0}\Performance", escapedName);
1738
1739 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, linkageKey, "Export", escapedName, componentId, false);
1740 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "-", null, componentId, false);
1741 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Library", library, componentId, false);
1742 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Open", openEntryPoint, componentId, false);
1743 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Collect", collectEntryPoint, componentId, false);
1744 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Close", closeEntryPoint, componentId, false);
1745 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "IsMultiInstance", YesNoType.Yes == multiInstance ? "#1" : "#0", componentId, false);
1746 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Counter Names", sbCounterNames.ToString(), componentId, false);
1747 this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, RegistryRootType.LocalMachine, performanceKey, "Counter Types", sbCounterTypes.ToString(), componentId, false);
1748 }
1749
1750 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4InstallPerfCounterData", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
1751 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4UninstallPerfCounterData", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
1752 }
1753
1754 /// <summary>
1755 /// Gets the performance counter language as a decimal number.
1756 /// </summary>
1757 /// <param name="sourceLineNumbers">Source line information about the owner element.</param>
1758 /// <param name="attribute">The attribute containing the value to get.</param>
1759 /// <returns>Numeric representation of the language as per WinNT.h.</returns>
1760 private int GetPerformanceCounterLanguage(SourceLineNumber sourceLineNumbers, XAttribute attribute)
1761 {
1762 int language = 0;
1763 if (String.Empty == attribute.Value)
1764 {
1765 this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName));
1766 }
1767 else
1768 {
1769 switch (attribute.Value)
1770 {
1771 case "afrikaans":
1772 language = 0x36;
1773 break;
1774 case "albanian":
1775 language = 0x1c;
1776 break;
1777 case "arabic":
1778 language = 0x01;
1779 break;
1780 case "armenian":
1781 language = 0x2b;
1782 break;
1783 case "assamese":
1784 language = 0x4d;
1785 break;
1786 case "azeri":
1787 language = 0x2c;
1788 break;
1789 case "basque":
1790 language = 0x2d;
1791 break;
1792 case "belarusian":
1793 language = 0x23;
1794 break;
1795 case "bengali":
1796 language = 0x45;
1797 break;
1798 case "bulgarian":
1799 language = 0x02;
1800 break;
1801 case "catalan":
1802 language = 0x03;
1803 break;
1804 case "chinese":
1805 language = 0x04;
1806 break;
1807 case "croatian":
1808 language = 0x1a;
1809 break;
1810 case "czech":
1811 language = 0x05;
1812 break;
1813 case "danish":
1814 language = 0x06;
1815 break;
1816 case "divehi":
1817 language = 0x65;
1818 break;
1819 case "dutch":
1820 language = 0x13;
1821 break;
1822 case "piglatin":
1823 case "english":
1824 language = 0x09;
1825 break;
1826 case "estonian":
1827 language = 0x25;
1828 break;
1829 case "faeroese":
1830 language = 0x38;
1831 break;
1832 case "farsi":
1833 language = 0x29;
1834 break;
1835 case "finnish":
1836 language = 0x0b;
1837 break;
1838 case "french":
1839 language = 0x0c;
1840 break;
1841 case "galician":
1842 language = 0x56;
1843 break;
1844 case "georgian":
1845 language = 0x37;
1846 break;
1847 case "german":
1848 language = 0x07;
1849 break;
1850 case "greek":
1851 language = 0x08;
1852 break;
1853 case "gujarati":
1854 language = 0x47;
1855 break;
1856 case "hebrew":
1857 language = 0x0d;
1858 break;
1859 case "hindi":
1860 language = 0x39;
1861 break;
1862 case "hungarian":
1863 language = 0x0e;
1864 break;
1865 case "icelandic":
1866 language = 0x0f;
1867 break;
1868 case "indonesian":
1869 language = 0x21;
1870 break;
1871 case "italian":
1872 language = 0x10;
1873 break;
1874 case "japanese":
1875 language = 0x11;
1876 break;
1877 case "kannada":
1878 language = 0x4b;
1879 break;
1880 case "kashmiri":
1881 language = 0x60;
1882 break;
1883 case "kazak":
1884 language = 0x3f;
1885 break;
1886 case "konkani":
1887 language = 0x57;
1888 break;
1889 case "korean":
1890 language = 0x12;
1891 break;
1892 case "kyrgyz":
1893 language = 0x40;
1894 break;
1895 case "latvian":
1896 language = 0x26;
1897 break;
1898 case "lithuanian":
1899 language = 0x27;
1900 break;
1901 case "macedonian":
1902 language = 0x2f;
1903 break;
1904 case "malay":
1905 language = 0x3e;
1906 break;
1907 case "malayalam":
1908 language = 0x4c;
1909 break;
1910 case "manipuri":
1911 language = 0x58;
1912 break;
1913 case "marathi":
1914 language = 0x4e;
1915 break;
1916 case "mongolian":
1917 language = 0x50;
1918 break;
1919 case "nepali":
1920 language = 0x61;
1921 break;
1922 case "norwegian":
1923 language = 0x14;
1924 break;
1925 case "oriya":
1926 language = 0x48;
1927 break;
1928 case "polish":
1929 language = 0x15;
1930 break;
1931 case "portuguese":
1932 language = 0x16;
1933 break;
1934 case "punjabi":
1935 language = 0x46;
1936 break;
1937 case "romanian":
1938 language = 0x18;
1939 break;
1940 case "russian":
1941 language = 0x19;
1942 break;
1943 case "sanskrit":
1944 language = 0x4f;
1945 break;
1946 case "serbian":
1947 language = 0x1a;
1948 break;
1949 case "sindhi":
1950 language = 0x59;
1951 break;
1952 case "slovak":
1953 language = 0x1b;
1954 break;
1955 case "slovenian":
1956 language = 0x24;
1957 break;
1958 case "spanish":
1959 language = 0x0a;
1960 break;
1961 case "swahili":
1962 language = 0x41;
1963 break;
1964 case "swedish":
1965 language = 0x1d;
1966 break;
1967 case "syriac":
1968 language = 0x5a;
1969 break;
1970 case "tamil":
1971 language = 0x49;
1972 break;
1973 case "tatar":
1974 language = 0x44;
1975 break;
1976 case "telugu":
1977 language = 0x4a;
1978 break;
1979 case "thai":
1980 language = 0x1e;
1981 break;
1982 case "turkish":
1983 language = 0x1f;
1984 break;
1985 case "ukrainian":
1986 language = 0x22;
1987 break;
1988 case "urdu":
1989 language = 0x20;
1990 break;
1991 case "uzbek":
1992 language = 0x43;
1993 break;
1994 case "vietnamese":
1995 language = 0x2a;
1996 break;
1997 default:
1998 this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName));
1999 break;
2000 }
2001 }
2002
2003 return language;
2004 }
2005
2006 /// <summary>
2007 /// Parses a performance counter element.
2008 /// </summary>
2009 /// <param name="element">Element to parse.</param>
2010 /// <param name="defaultLanguage">Default language for the performance counter.</param>
2011 private ParsedPerformanceCounter ParsePerformanceCounterElement(Intermediate intermediate, IntermediateSection section, XElement element, int defaultLanguage)
2012 {
2013 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2014 ParsedPerformanceCounter parsedPerformanceCounter = null;
2015 string name = null;
2016 string help = null;
2017 var type = System.Diagnostics.PerformanceCounterType.NumberOfItems32;
2018 int language = defaultLanguage;
2019
2020 foreach (var attrib in element.Attributes())
2021 {
2022 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2023 {
2024 switch (attrib.Name.LocalName)
2025 {
2026 case "Help":
2027 help = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2028 break;
2029 case "Name":
2030 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2031 break;
2032 case "Type":
2033 type = this.GetPerformanceCounterType(sourceLineNumbers, attrib);
2034 break;
2035 case "Language":
2036 language = this.GetPerformanceCounterLanguage(sourceLineNumbers, attrib);
2037 break;
2038 default:
2039 this.ParseHelper.UnexpectedAttribute(element, attrib);
2040 break;
2041 }
2042 }
2043 else
2044 {
2045 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2046 }
2047 }
2048
2049 if (null == name)
2050 {
2051 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
2052 }
2053
2054 if (null == help)
2055 {
2056 this.Messaging.Write(UtilWarnings.RequiredAttributeForWindowsXP(sourceLineNumbers, element.Name.LocalName, "Help"));
2057 }
2058
2059 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2060
2061 if (!this.Messaging.EncounteredError)
2062 {
2063 parsedPerformanceCounter = new ParsedPerformanceCounter(name, help, type, language);
2064 }
2065
2066 return parsedPerformanceCounter;
2067 }
2068
2069 /// <summary>
2070 /// Gets the performance counter type.
2071 /// </summary>
2072 /// <param name="sourceLineNumbers">Source line information about the owner element.</param>
2073 /// <param name="attribute">The attribute containing the value to get.</param>
2074 /// <returns>Numeric representation of the language as per WinNT.h.</returns>
2075 private System.Diagnostics.PerformanceCounterType GetPerformanceCounterType(SourceLineNumber sourceLineNumbers, XAttribute attribute)
2076 {
2077 var type = System.Diagnostics.PerformanceCounterType.NumberOfItems32;
2078 if (String.Empty == attribute.Value)
2079 {
2080 this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName));
2081 }
2082 else
2083 {
2084 switch (attribute.Value)
2085 {
2086 case "averageBase":
2087 type = System.Diagnostics.PerformanceCounterType.AverageBase;
2088 break;
2089 case "averageCount64":
2090 type = System.Diagnostics.PerformanceCounterType.AverageCount64;
2091 break;
2092 case "averageTimer32":
2093 type = System.Diagnostics.PerformanceCounterType.AverageTimer32;
2094 break;
2095 case "counterDelta32":
2096 type = System.Diagnostics.PerformanceCounterType.CounterDelta32;
2097 break;
2098 case "counterTimerInverse":
2099 type = System.Diagnostics.PerformanceCounterType.CounterTimerInverse;
2100 break;
2101 case "sampleFraction":
2102 type = System.Diagnostics.PerformanceCounterType.SampleFraction;
2103 break;
2104 case "timer100Ns":
2105 type = System.Diagnostics.PerformanceCounterType.Timer100Ns;
2106 break;
2107 case "counterTimer":
2108 type = System.Diagnostics.PerformanceCounterType.CounterTimer;
2109 break;
2110 case "rawFraction":
2111 type = System.Diagnostics.PerformanceCounterType.RawFraction;
2112 break;
2113 case "timer100NsInverse":
2114 type = System.Diagnostics.PerformanceCounterType.Timer100NsInverse;
2115 break;
2116 case "counterMultiTimer":
2117 type = System.Diagnostics.PerformanceCounterType.CounterMultiTimer;
2118 break;
2119 case "counterMultiTimer100Ns":
2120 type = System.Diagnostics.PerformanceCounterType.CounterMultiTimer100Ns;
2121 break;
2122 case "counterMultiTimerInverse":
2123 type = System.Diagnostics.PerformanceCounterType.CounterMultiTimerInverse;
2124 break;
2125 case "counterMultiTimer100NsInverse":
2126 type = System.Diagnostics.PerformanceCounterType.CounterMultiTimer100NsInverse;
2127 break;
2128 case "elapsedTime":
2129 type = System.Diagnostics.PerformanceCounterType.ElapsedTime;
2130 break;
2131 case "sampleBase":
2132 type = System.Diagnostics.PerformanceCounterType.SampleBase;
2133 break;
2134 case "rawBase":
2135 type = System.Diagnostics.PerformanceCounterType.RawBase;
2136 break;
2137 case "counterMultiBase":
2138 type = System.Diagnostics.PerformanceCounterType.CounterMultiBase;
2139 break;
2140 case "rateOfCountsPerSecond64":
2141 type = System.Diagnostics.PerformanceCounterType.RateOfCountsPerSecond64;
2142 break;
2143 case "rateOfCountsPerSecond32":
2144 type = System.Diagnostics.PerformanceCounterType.RateOfCountsPerSecond32;
2145 break;
2146 case "countPerTimeInterval64":
2147 type = System.Diagnostics.PerformanceCounterType.CountPerTimeInterval64;
2148 break;
2149 case "countPerTimeInterval32":
2150 type = System.Diagnostics.PerformanceCounterType.CountPerTimeInterval32;
2151 break;
2152 case "sampleCounter":
2153 type = System.Diagnostics.PerformanceCounterType.SampleCounter;
2154 break;
2155 case "counterDelta64":
2156 type = System.Diagnostics.PerformanceCounterType.CounterDelta64;
2157 break;
2158 case "numberOfItems64":
2159 type = System.Diagnostics.PerformanceCounterType.NumberOfItems64;
2160 break;
2161 case "numberOfItems32":
2162 type = System.Diagnostics.PerformanceCounterType.NumberOfItems32;
2163 break;
2164 case "numberOfItemsHEX64":
2165 type = System.Diagnostics.PerformanceCounterType.NumberOfItemsHEX64;
2166 break;
2167 case "numberOfItemsHEX32":
2168 type = System.Diagnostics.PerformanceCounterType.NumberOfItemsHEX32;
2169 break;
2170 default:
2171 this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName));
2172 break;
2173 }
2174 }
2175
2176 return type;
2177 }
2178
2179 /// <summary>
2180 /// Parses a perf counter element.
2181 /// </summary>
2182 /// <param name="element">Element to parse.</param>
2183 /// <param name="componentId">Identifier of parent component.</param>
2184 /// <param name="fileId">Identifier of referenced file.</param>
2185 private void ParsePerfCounterElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId)
2186 {
2187 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2188 string name = null;
2189
2190 this.Messaging.Write(UtilWarnings.DeprecatedPerfCounterElement(sourceLineNumbers));
2191
2192 foreach (var attrib in element.Attributes())
2193 {
2194 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2195 {
2196 switch (attrib.Name.LocalName)
2197 {
2198 case "Name":
2199 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2200 break;
2201 default:
2202 this.ParseHelper.UnexpectedAttribute(element, attrib);
2203 break;
2204 }
2205 }
2206 else
2207 {
2208 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2209 }
2210 }
2211
2212 if (null == name)
2213 {
2214 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
2215 }
2216
2217 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2218
2219 if (!this.Messaging.EncounteredError)
2220 {
2221 section.AddSymbol(new PerfmonSymbol(sourceLineNumbers)
2222 {
2223 ComponentRef = componentId,
2224 File = $"[#{fileId}]",
2225 Name = name,
2226 });
2227 }
2228
2229 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2230 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonUninstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2231 }
2232
2233
2234 /// <summary>
2235 /// Parses a perf manifest element.
2236 /// </summary>
2237 /// <param name="element">Element to parse.</param>
2238 /// <param name="componentId">Identifier of parent component.</param>
2239 /// <param name="fileId">Identifier of referenced file.</param>
2240 private void ParsePerfCounterManifestElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId)
2241 {
2242 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2243 string resourceFileDirectory = null;
2244
2245 foreach (var attrib in element.Attributes())
2246 {
2247 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2248 {
2249 switch (attrib.Name.LocalName)
2250 {
2251 case "ResourceFileDirectory":
2252 resourceFileDirectory = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2253 break;
2254 default:
2255 this.ParseHelper.UnexpectedAttribute(element, attrib);
2256 break;
2257 }
2258 }
2259 else
2260 {
2261 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2262 }
2263 }
2264
2265 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2266
2267 if (!this.Messaging.EncounteredError)
2268 {
2269 section.AddSymbol(new PerfmonManifestSymbol(sourceLineNumbers)
2270 {
2271 ComponentRef = componentId,
2272 File = $"[#{fileId}]",
2273 ResourceFileDirectory = resourceFileDirectory,
2274 });
2275 }
2276
2277 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonManifestRegister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2278 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigurePerfmonManifestUnregister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2279 }
2280
2281 /// <summary>
2282 /// Parses a format files element.
2283 /// </summary>
2284 /// <param name="element">Element to parse.</param>
2285 /// <param name="fileId">Identifier of referenced file.</param>
2286 /// <param name="win64">Flag to determine whether the component is 64-bit.</param>
2287 private void ParseFormatFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string fileId, bool win64)
2288 {
2289 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2290 string binaryId = null;
2291
2292 foreach (var attrib in element.Attributes())
2293 {
2294 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2295 {
2296 switch (attrib.Name.LocalName)
2297 {
2298 case "BinaryRef":
2299 binaryId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2300 break;
2301 default:
2302 this.ParseHelper.UnexpectedAttribute(element, attrib);
2303 break;
2304 }
2305 }
2306 else
2307 {
2308 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2309 }
2310 }
2311
2312 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2313
2314 if (null == binaryId)
2315 {
2316 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "BinaryRef"));
2317 }
2318
2319 if (!this.Messaging.EncounteredError)
2320 {
2321 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFormatFiles", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2322
2323 section.AddSymbol(new WixFormatFilesSymbol(sourceLineNumbers)
2324 {
2325 BinaryRef = binaryId,
2326 FileRef = fileId,
2327 });
2328
2329 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Binary, binaryId);
2330 }
2331 }
2332
2333 /// <summary>
2334 /// Parses a event manifest element.
2335 /// </summary>
2336 /// <param name="element">Element to parse.</param>
2337 /// <param name="componentId">Identifier of parent component.</param>
2338 /// <param name="fileId">Identifier of referenced file.</param>
2339 private void ParseEventManifestElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId)
2340 {
2341 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2342 string messageFile = null;
2343 string resourceFile = null;
2344 string parameterFile = null;
2345
2346 foreach (var attrib in element.Attributes())
2347 {
2348 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2349 {
2350 switch (attrib.Name.LocalName)
2351 {
2352 case "MessageFile":
2353 messageFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2354 break;
2355 case "ResourceFile":
2356 resourceFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2357 break;
2358 case "ParameterFile":
2359 parameterFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2360 break;
2361 default:
2362 this.ParseHelper.UnexpectedAttribute(element, attrib);
2363 break;
2364 }
2365 }
2366 else
2367 {
2368 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2369 }
2370 }
2371
2372 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2373
2374 if (!this.Messaging.EncounteredError)
2375 {
2376 section.AddSymbol(new EventManifestSymbol(sourceLineNumbers)
2377 {
2378 ComponentRef = componentId,
2379 File = $"[#{fileId}]",
2380 });
2381
2382 if (null != messageFile)
2383 {
2384 section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, $"Config_{fileId}MessageFile"))
2385 {
2386 File = $"[#{fileId}]",
2387 ElementPath = "/*/*/*/*[\\[]@messageFileName[\\]]",
2388 Name = "messageFileName",
2389 Value = messageFile,
2390 Flags = 4 | 0x00001000, //bulk write | preserve modified date
2391 ComponentRef = componentId,
2392 });
2393 }
2394 if (null != parameterFile)
2395 {
2396 section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, $"Config_{fileId}ParameterFile"))
2397 {
2398 File = $"[#{fileId}]",
2399 ElementPath = "/*/*/*/*[\\[]@parameterFileName[\\]]",
2400 Name = "parameterFileName",
2401 Value = parameterFile,
2402 Flags = 4 | 0x00001000, //bulk write | preserve modified date
2403 ComponentRef = componentId,
2404 });
2405 }
2406 if (null != resourceFile)
2407 {
2408 section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, $"Config_{fileId}ResourceFile"))
2409 {
2410 File = $"[#{fileId}]",
2411 ElementPath = "/*/*/*/*[\\[]@resourceFileName[\\]]",
2412 Name = "resourceFileName",
2413 Value = resourceFile,
2414 Flags = 4 | 0x00001000, //bulk write | preserve modified date
2415 ComponentRef = componentId,
2416 });
2417 }
2418
2419 }
2420
2421 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureEventManifestRegister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2422 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureEventManifestUnregister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2423
2424 if (null != messageFile || null != parameterFile || null != resourceFile)
2425 {
2426 this.AddReferenceToSchedXmlFile(sourceLineNumbers, section);
2427 }
2428 }
2429
2430 /// <summary>
2431 /// Parses a PermissionEx element.
2432 /// </summary>
2433 /// <param name="element">Element to parse.</param>
2434 /// <param name="objectId">Identifier of object to be secured.</param>
2435 /// <param name="componentId">Identifier of component, used to determine install state.</param>
2436 /// <param name="win64">Flag to determine whether the component is 64-bit.</param>
2437 /// <param name="tableName">Name of table that contains objectId.</param>
2438 private void ParsePermissionExElement(Intermediate intermediate, IntermediateSection section, XElement element, string objectId, string componentId, bool win64, string tableName)
2439 {
2440 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2441 var bits = new BitArray(32);
2442 string domain = null;
2443 string[] specialPermissions = null;
2444 string user = null;
2445 var attributes = WixPermissionExAttributes.Inheritable; // default to inheritable.
2446
2447 var permissionType = PermissionType.SecureObjects;
2448
2449 switch (tableName)
2450 {
2451 case "CreateFolder":
2452 specialPermissions = UtilConstants.FolderPermissions;
2453 break;
2454 case "File":
2455 specialPermissions = UtilConstants.FilePermissions;
2456 break;
2457 case "Registry":
2458 specialPermissions = UtilConstants.RegistryPermissions;
2459 if (String.IsNullOrEmpty(objectId))
2460 {
2461 this.Messaging.Write(UtilErrors.InvalidRegistryObject(sourceLineNumbers, element.Parent.Name.LocalName));
2462 }
2463 break;
2464 case "ServiceInstall":
2465 specialPermissions = UtilConstants.ServicePermissions;
2466 permissionType = PermissionType.SecureObjects;
2467 break;
2468 default:
2469 this.ParseHelper.UnexpectedElement(element.Parent, element);
2470 break;
2471 }
2472
2473 foreach (var attrib in element.Attributes())
2474 {
2475 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2476 {
2477 switch (attrib.Name.LocalName)
2478 {
2479 case "Domain":
2480 if (PermissionType.FileSharePermissions == permissionType)
2481 {
2482 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName));
2483 }
2484 domain = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2485 break;
2486 case "Inheritable":
2487 if (this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.No)
2488 {
2489 attributes &= ~WixPermissionExAttributes.Inheritable;
2490 }
2491 break;
2492 case "User":
2493 user = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2494 break;
2495 default:
2496 var attribValue = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
2497 if (!this.TrySetBitFromName(UtilConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16))
2498 {
2499 if (!this.TrySetBitFromName(UtilConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28))
2500 {
2501 if (!this.TrySetBitFromName(specialPermissions, attrib.Name.LocalName, attribValue, bits, 0))
2502 {
2503 this.ParseHelper.UnexpectedAttribute(element, attrib);
2504 break;
2505 }
2506 }
2507 }
2508 break;
2509 }
2510 }
2511 else
2512 {
2513 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2514 }
2515 }
2516
2517 var permission = this.CreateIntegerFromBitArray(bits);
2518
2519 if (null == user)
2520 {
2521 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "User"));
2522 }
2523
2524 if (Int32.MinValue == permission) // just GENERIC_READ, which is MSI_NULL
2525 {
2526 this.Messaging.Write(ErrorMessages.GenericReadNotAllowed(sourceLineNumbers));
2527 }
2528
2529 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2530
2531 if (!this.Messaging.EncounteredError)
2532 {
2533 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedSecureObjects", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2534
2535 var id = this.ParseHelper.CreateIdentifier("sec", objectId, tableName, domain, user);
2536 section.AddSymbol(new SecureObjectsSymbol(sourceLineNumbers, id)
2537 {
2538 SecureObject = objectId,
2539 Table = tableName,
2540 Domain = domain,
2541 User = user,
2542 Attributes = attributes,
2543 Permission = permission,
2544 ComponentRef = componentId,
2545 });
2546 }
2547 }
2548
2549 /// <summary>
2550 /// Parses a ProductSearch element.
2551 /// </summary>
2552 /// <param name="element">Element to parse.</param>
2553 private void ParseProductSearchElement(Intermediate intermediate, IntermediateSection section, XElement element)
2554 {
2555 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2556 Identifier id = null;
2557 string variable = null;
2558 string condition = null;
2559 string after = null;
2560 string productCode = null;
2561 string upgradeCode = null;
2562 var attributes = WixProductSearchAttributes.Version;
2563
2564 foreach (var attrib in element.Attributes())
2565 {
2566 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2567 {
2568 switch (attrib.Name.LocalName)
2569 {
2570 case "Id":
2571 case "Variable":
2572 case "Condition":
2573 case "After":
2574 this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after);
2575 break;
2576 case "ProductCode":
2577 productCode = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
2578 break;
2579 case "UpgradeCode":
2580 upgradeCode = this.ParseHelper.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
2581 break;
2582 case "Result":
2583 var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2584 switch (result)
2585 {
2586 case "version":
2587 attributes = WixProductSearchAttributes.Version;
2588 break;
2589 case "language":
2590 attributes = WixProductSearchAttributes.Language;
2591 break;
2592 case "state":
2593 attributes = WixProductSearchAttributes.State;
2594 break;
2595 case "assignment":
2596 attributes = WixProductSearchAttributes.Assignment;
2597 break;
2598 default:
2599 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "version", "language", "state", "assignment"));
2600 break;
2601 }
2602 break;
2603 default:
2604 this.ParseHelper.UnexpectedAttribute(element, attrib);
2605 break;
2606 }
2607 }
2608 else
2609 {
2610 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2611 }
2612 }
2613
2614 if (null == upgradeCode && null == productCode)
2615 {
2616 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ProductCode", "UpgradeCode", true));
2617 }
2618
2619 if (null != upgradeCode && null != productCode)
2620 {
2621 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "UpgradeCode", "ProductCode"));
2622 }
2623
2624 if (null == id)
2625 {
2626 id = this.ParseHelper.CreateIdentifier("wps", variable, condition, after, (productCode == null ? upgradeCode : productCode), attributes.ToString());
2627 }
2628
2629 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2630
2631 this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null);
2632
2633 if (!this.Messaging.EncounteredError)
2634 {
2635 // set an additional flag if this is an upgrade code
2636 if (null != upgradeCode)
2637 {
2638 attributes |= WixProductSearchAttributes.UpgradeCode;
2639 }
2640
2641 section.AddSymbol(new WixProductSearchSymbol(sourceLineNumbers, id)
2642 {
2643 Guid = productCode ?? upgradeCode,
2644 Attributes = attributes,
2645 });
2646 }
2647 }
2648
2649 /// <summary>
2650 /// Parses a RegistrySearch element.
2651 /// </summary>
2652 /// <param name="element">Element to parse.</param>
2653 private void ParseRegistrySearchElement(Intermediate intermediate, IntermediateSection section, XElement element)
2654 {
2655 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2656 Identifier id = null;
2657 string variable = null;
2658 string condition = null;
2659 string after = null;
2660 RegistryRootType? root = null;
2661 string key = null;
2662 string value = null;
2663 var expand = YesNoType.NotSet;
2664 var win64 = this.Context.IsCurrentPlatform64Bit;
2665 var attributes = WixRegistrySearchAttributes.Raw | WixRegistrySearchAttributes.WantValue;
2666
2667 foreach (var attrib in element.Attributes())
2668 {
2669 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2670 {
2671 switch (attrib.Name.LocalName)
2672 {
2673 case "Id":
2674 case "Variable":
2675 case "Condition":
2676 case "After":
2677 this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after);
2678 break;
2679 case "Bitness":
2680 var bitnessValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2681 switch (bitnessValue)
2682 {
2683 case "always32":
2684 win64 = false;
2685 break;
2686 case "always64":
2687 win64 = true;
2688 break;
2689 case "default":
2690 case "":
2691 break;
2692 default:
2693 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Name.LocalName, attrib.Name.LocalName, bitnessValue, "default", "always32", "always64"));
2694 break;
2695 }
2696 break;
2697 case "Root":
2698 root = this.ParseHelper.GetAttributeRegistryRootValue(sourceLineNumbers, attrib, false);
2699 break;
2700 case "Key":
2701 key = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2702 break;
2703 case "Value":
2704 value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2705 break;
2706 case "ExpandEnvironmentVariables":
2707 expand = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
2708 break;
2709 case "Format":
2710 string format = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2711 switch (format)
2712 {
2713 case "raw":
2714 attributes |= WixRegistrySearchAttributes.Raw;
2715 break;
2716 case "compatible":
2717 attributes |= WixRegistrySearchAttributes.Compatible;
2718 break;
2719 default:
2720 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, format, "raw", "compatible"));
2721 break;
2722 }
2723 break;
2724 case "Result":
2725 var result = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2726 switch (result)
2727 {
2728 case "exists":
2729 attributes |= WixRegistrySearchAttributes.WantExists;
2730 break;
2731 case "value":
2732 attributes |= WixRegistrySearchAttributes.WantValue;
2733 break;
2734 default:
2735 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attrib.Parent.Name.LocalName, attrib.Name.LocalName, result, "exists", "value"));
2736 break;
2737 }
2738 break;
2739 default:
2740 this.ParseHelper.UnexpectedAttribute(element, attrib);
2741 break;
2742 }
2743 }
2744 else
2745 {
2746 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2747 }
2748 }
2749
2750 if (!root.HasValue)
2751 {
2752 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Root"));
2753 }
2754
2755 if (null == key)
2756 {
2757 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Key"));
2758 }
2759
2760 if (null == id)
2761 {
2762 id = this.ParseHelper.CreateIdentifier("wrs", variable, condition, after, root.ToString(), key, value, attributes.ToString());
2763 }
2764
2765 if (expand == YesNoType.Yes)
2766 {
2767 if (0 != (attributes & WixRegistrySearchAttributes.WantExists))
2768 {
2769 this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "ExpandEnvironmentVariables", expand.ToString(), "Result", "exists"));
2770 }
2771
2772 attributes |= WixRegistrySearchAttributes.ExpandEnvironmentVariables;
2773 }
2774
2775 if (win64)
2776 {
2777 attributes |= WixRegistrySearchAttributes.Win64;
2778 }
2779
2780 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2781
2782 this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null);
2783
2784 if (!this.Messaging.EncounteredError)
2785 {
2786 section.AddSymbol(new WixRegistrySearchSymbol(sourceLineNumbers, id)
2787 {
2788 Root = root.Value,
2789 Key = key,
2790 Value = value,
2791 Attributes = attributes,
2792 });
2793 }
2794 }
2795
2796 /// <summary>
2797 /// Parses a RemoveFolderEx element.
2798 /// </summary>
2799 /// <param name="element">Element to parse.</param>
2800 /// <param name="componentId">Identifier of parent component.</param>
2801 private void ParseRemoveFolderExElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
2802 {
2803 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2804 Identifier id = null;
2805 var mode = WixRemoveFolderExInstallMode.Uninstall;
2806 string property = null;
2807 string condition = null;
2808
2809 foreach (var attrib in element.Attributes())
2810 {
2811 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2812 {
2813 switch (attrib.Name.LocalName)
2814 {
2815 case "Condition":
2816 condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2817 break;
2818 case "Id":
2819 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
2820 break;
2821 case "On":
2822 var onValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2823 if (onValue.Length == 0)
2824 {
2825 }
2826 else
2827 {
2828 switch (onValue)
2829 {
2830 case "install":
2831 mode = WixRemoveFolderExInstallMode.Install;
2832 break;
2833 case "uninstall":
2834 mode = WixRemoveFolderExInstallMode.Uninstall;
2835 break;
2836 case "both":
2837 mode = WixRemoveFolderExInstallMode.Both;
2838 break;
2839 default:
2840 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "On", onValue, "install", "uninstall", "both"));
2841 break;
2842 }
2843 }
2844 break;
2845 case "Property":
2846 property = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2847 break;
2848 default:
2849 this.ParseHelper.UnexpectedAttribute(element, attrib);
2850 break;
2851 }
2852 }
2853 else
2854 {
2855 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2856 }
2857 }
2858
2859 if (String.IsNullOrEmpty(property))
2860 {
2861 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Property"));
2862 }
2863
2864 if (id == null)
2865 {
2866 id = this.ParseHelper.CreateIdentifier("wrf", componentId, property, mode.ToString());
2867 }
2868
2869 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2870
2871 if (!this.Messaging.EncounteredError)
2872 {
2873 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4RemoveFoldersEx", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2874
2875 section.AddSymbol(new WixRemoveFolderExSymbol(sourceLineNumbers, id)
2876 {
2877 ComponentRef = componentId,
2878 Property = property,
2879 InstallMode = mode,
2880 Condition = condition
2881 });
2882
2883 this.ParseHelper.EnsureTable(section, sourceLineNumbers, "RemoveFile");
2884 }
2885 }
2886
2887 /// <summary>
2888 /// Parses a RemoveRegistryKeyEx element.
2889 /// </summary>
2890 /// <param name="node">Element to parse.</param>
2891 /// <param name="componentId">Identifier of parent component.</param>
2892 private void ParseRemoveRegistryKeyExElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
2893 {
2894 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2895 Identifier id = null;
2896 var mode = WixRemoveRegistryKeyExInstallMode.Uninstall;
2897 string condition = null;
2898 RegistryRootType? root = null;
2899 string key = null;
2900
2901 foreach (var attrib in element.Attributes())
2902 {
2903 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2904 {
2905 switch (attrib.Name.LocalName)
2906 {
2907 case "Condition":
2908 condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2909 break;
2910 case "Id":
2911 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
2912 break;
2913 case "On":
2914 var actionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2915 switch (actionValue)
2916 {
2917 case "":
2918 break;
2919 case "install":
2920 mode = WixRemoveRegistryKeyExInstallMode.Install;
2921 break;
2922 case "uninstall":
2923 mode = WixRemoveRegistryKeyExInstallMode.Uninstall;
2924 break;
2925 default:
2926 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "On", actionValue, "install", "uninstall"));
2927 break;
2928 }
2929 break;
2930 case "Root":
2931 root = this.ParseHelper.GetAttributeRegistryRootValue(sourceLineNumbers, attrib, false);
2932 break;
2933 case "Key":
2934 key = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2935 break;
2936 default:
2937 this.ParseHelper.UnexpectedAttribute(element, attrib);
2938 break;
2939 }
2940 }
2941 else
2942 {
2943 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2944 }
2945 }
2946
2947 if (!root.HasValue)
2948 {
2949 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Root"));
2950 }
2951
2952 if (key == null)
2953 {
2954 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Key"));
2955 }
2956
2957 if (id == null)
2958 {
2959 id = this.ParseHelper.CreateIdentifier("rrx", componentId, condition, root.ToString(), key, mode.ToString());
2960 }
2961
2962 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2963
2964 if (!this.Messaging.EncounteredError)
2965 {
2966 this.ParseHelper.EnsureTable(section, sourceLineNumbers, "Registry");
2967 this.ParseHelper.EnsureTable(section, sourceLineNumbers, "RemoveRegistry");
2968 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4RemoveRegistryKeysEx", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2969
2970 section.AddSymbol(new WixRemoveRegistryKeyExSymbol(sourceLineNumbers, id)
2971 {
2972 ComponentRef = componentId,
2973 Root = root.Value,
2974 Key = key,
2975 InstallMode = mode,
2976 Condition = condition
2977 });
2978 }
2979 }
2980
2981 /// <summary>
2982 /// Parses a RestartResource element.
2983 /// </summary>
2984 /// <param name="element">The element to parse.</param>
2985 /// <param name="componentId">The identity of the parent component.</param>
2986 private void ParseRestartResourceElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
2987 {
2988 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2989 Identifier id = null;
2990 string resource = null;
2991 WixRestartResourceAttributes? attributes = null;
2992
2993 foreach (var attrib in element.Attributes())
2994 {
2995 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2996 {
2997 switch (attrib.Name.LocalName)
2998 {
2999 case "Id":
3000 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
3001 break;
3002
3003 case "Path":
3004 resource = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3005 attributes = WixRestartResourceAttributes.Filename;
3006 break;
3007
3008 case "ProcessName":
3009 resource = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3010 attributes = WixRestartResourceAttributes.ProcessName;
3011 break;
3012
3013 case "ServiceName":
3014 resource = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3015 attributes = WixRestartResourceAttributes.ServiceName;
3016 break;
3017
3018 default:
3019 this.ParseHelper.UnexpectedAttribute(element, attrib);
3020 break;
3021 }
3022 }
3023 else
3024 {
3025 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
3026 }
3027 }
3028
3029 // Validate the attribute.
3030 if (id == null)
3031 {
3032 id = this.ParseHelper.CreateIdentifier("wrr", componentId, resource, attributes.ToString());
3033 }
3034
3035 if (!attributes.HasValue)
3036 {
3037 this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "Path", "ProcessName", "ServiceName"));
3038 }
3039
3040 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
3041
3042 if (!this.Messaging.EncounteredError)
3043 {
3044 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4RegisterRestartResources", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
3045
3046 section.AddSymbol(new WixRestartResourceSymbol(sourceLineNumbers, id)
3047 {
3048 ComponentRef = componentId,
3049 Resource = resource,
3050 Attributes = attributes,
3051 });
3052 }
3053 }
3054
3055 /// <summary>
3056 /// Parses a service configuration element.
3057 /// </summary>
3058 /// <param name="element">Element to parse.</param>
3059 /// <param name="componentId">Identifier of parent component.</param>
3060 /// <param name="parentTableName">Name of parent element.</param>
3061 /// <param name="parentTableServiceName">Optional name of service </param>
3062 private void ParseServiceConfigElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentTableName, string parentTableServiceName)
3063 {
3064 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
3065 string firstFailureActionType = null;
3066 var newService = false;
3067 string programCommandLine = null;
3068 string rebootMessage = null;
3069 var resetPeriod = CompilerConstants.IntegerNotSet;
3070 var restartServiceDelay = CompilerConstants.IntegerNotSet;
3071 string secondFailureActionType = null;
3072 string serviceName = null;
3073 string thirdFailureActionType = null;
3074
3075 foreach (var attrib in element.Attributes())
3076 {
3077 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
3078 {
3079 switch (attrib.Name.LocalName)
3080 {
3081 case "FirstFailureActionType":
3082 firstFailureActionType = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3083 break;
3084 case "ProgramCommandLine":
3085 programCommandLine = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3086 break;
3087 case "RebootMessage":
3088 rebootMessage = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3089 break;
3090 case "ResetPeriodInDays":
3091 resetPeriod = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue);
3092 break;
3093 case "RestartServiceDelayInSeconds":
3094 restartServiceDelay = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue);
3095 break;
3096 case "SecondFailureActionType":
3097 secondFailureActionType = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3098 break;
3099 case "ServiceName":
3100 serviceName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3101 break;
3102 case "ThirdFailureActionType":
3103 thirdFailureActionType = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3104 break;
3105 default:
3106 this.ParseHelper.UnexpectedAttribute(element, attrib);
3107 break;
3108 }
3109 }
3110 else
3111 {
3112 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
3113 }
3114 }
3115
3116 // if this element is a child of ServiceInstall then ignore the service name provided.
3117 if ("ServiceInstall" == parentTableName)
3118 {
3119 // TODO: the ServiceName attribute should not be allowed in this case (the overwriting behavior may confuse users)
3120 serviceName = parentTableServiceName;
3121 newService = true;
3122 }
3123 else
3124 {
3125 // not a child of ServiceInstall, so ServiceName must have been provided
3126 if (null == serviceName)
3127 {
3128 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ServiceName"));
3129 }
3130 }
3131
3132 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
3133
3134 if (!this.Messaging.EncounteredError)
3135 {
3136 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedServiceConfig", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
3137
3138 section.AddSymbol(new ServiceConfigSymbol(sourceLineNumbers)
3139 {
3140 ServiceName = serviceName,
3141 ComponentRef = componentId,
3142 NewService = newService ? 1 : 0,
3143 FirstFailureActionType = firstFailureActionType,
3144 SecondFailureActionType = secondFailureActionType,
3145 ThirdFailureActionType = thirdFailureActionType,
3146 ResetPeriodInDays = resetPeriod,
3147 RestartServiceDelayInSeconds = restartServiceDelay,
3148 ProgramCommandLine = programCommandLine,
3149 RebootMessage = rebootMessage,
3150 });
3151 }
3152 }
3153
3154 /// <summary>
3155 /// Parses a touch file element.
3156 /// </summary>
3157 /// <param name="element">Element to parse.</param>
3158 /// <param name="componentId">Identifier of parent component.</param>
3159 /// <param name="win64">Indicates whether the path is a 64-bit path.</param>
3160 private void ParseTouchFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, bool win64)
3161 {
3162 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
3163 Identifier id = null;
3164 string path = null;
3165 var onInstall = YesNoType.NotSet;
3166 var onReinstall = YesNoType.NotSet;
3167 var onUninstall = YesNoType.NotSet;
3168 var nonvital = YesNoType.NotSet;
3169 int attributes = 0;
3170
3171 foreach (var attrib in element.Attributes())
3172 {
3173 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
3174 {
3175 switch (attrib.Name.LocalName)
3176 {
3177 case "Id":
3178 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
3179 break;
3180 case "Path":
3181 path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3182 break;
3183 case "OnInstall":
3184 onInstall = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
3185 break;
3186 case "OnReinstall":
3187 onReinstall = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
3188 break;
3189 case "OnUninstall":
3190 onUninstall = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
3191 break;
3192 case "Nonvital":
3193 nonvital = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
3194 break;
3195 default:
3196 this.ParseHelper.UnexpectedAttribute(element, attrib);
3197 break;
3198 }
3199 }
3200 else
3201 {
3202 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
3203 }
3204 }
3205
3206 if (null == path)
3207 {
3208 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path"));
3209 }
3210
3211 // If none of the scheduling actions are set, default to touching on install and reinstall.
3212 if (YesNoType.NotSet == onInstall && YesNoType.NotSet == onReinstall && YesNoType.NotSet == onUninstall)
3213 {
3214 onInstall = YesNoType.Yes;
3215 onReinstall = YesNoType.Yes;
3216 }
3217
3218 attributes |= YesNoType.Yes == onInstall ? 0x1 : 0;
3219 attributes |= YesNoType.Yes == onReinstall ? 0x2 : 0;
3220 attributes |= YesNoType.Yes == onUninstall ? 0x4 : 0;
3221 attributes |= win64 ? 0x10 : 0;
3222 attributes |= YesNoType.Yes == nonvital ? 0 : 0x20;
3223
3224 if (null == id)
3225 {
3226 id = this.ParseHelper.CreateIdentifier("tf", path, attributes.ToString());
3227 }
3228
3229 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
3230
3231 if (!this.Messaging.EncounteredError)
3232 {
3233 section.AddSymbol(new WixTouchFileSymbol(sourceLineNumbers, id)
3234 {
3235 ComponentRef = componentId,
3236 Path = path,
3237 Attributes = attributes,
3238 });
3239
3240 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4TouchFileDuringInstall", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
3241 }
3242 }
3243
3244 /// <summary>
3245 /// Parses an user element.
3246 /// </summary>
3247 /// <param name="element">Element to parse.</param>
3248 /// <param name="componentId">Optional identifier of parent component.</param>
3249 private void ParseUserElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
3250 {
3251 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
3252 Identifier id = null;
3253 int attributes = 0;
3254 string domain = null;
3255 string name = null;
3256 string password = null;
3257
3258 foreach (var attrib in element.Attributes())
3259 {
3260 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
3261 {
3262 switch (attrib.Name.LocalName)
3263 {
3264 case "Id":
3265 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
3266 break;
3267 case "CanNotChangePassword":
3268 if (null == componentId)
3269 {
3270 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3271 }
3272
3273 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3274 {
3275 attributes |= UserPasswdCantChange;
3276 }
3277 break;
3278 case "CreateUser":
3279 if (null == componentId)
3280 {
3281 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3282 }
3283
3284 if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3285 {
3286 attributes |= UserDontCreateUser;
3287 }
3288 break;
3289 case "Disabled":
3290 if (null == componentId)
3291 {
3292 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3293 }
3294
3295 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3296 {
3297 attributes |= UserDisableAccount;
3298 }
3299 break;
3300 case "Domain":
3301 domain = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3302 break;
3303 case "FailIfExists":
3304 if (null == componentId)
3305 {
3306 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3307 }
3308
3309 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3310 {
3311 attributes |= UserFailIfExists;
3312 }
3313 break;
3314 case "LogonAsService":
3315 if (null == componentId)
3316 {
3317 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3318 }
3319 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3320 {
3321 attributes |= UserLogonAsService;
3322 }
3323 break;
3324 case "LogonAsBatchJob":
3325 if (null == componentId)
3326 {
3327 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3328 }
3329 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3330 {
3331 attributes |= UserLogonAsBatchJob;
3332 }
3333 break;
3334 case "Name":
3335 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3336 break;
3337 case "Password":
3338 password = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3339 break;
3340 case "PasswordExpired":
3341 if (null == componentId)
3342 {
3343 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3344 }
3345
3346 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3347 {
3348 attributes |= UserPasswdChangeReqdOnLogin;
3349 }
3350 break;
3351 case "PasswordNeverExpires":
3352 if (null == componentId)
3353 {
3354 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3355 }
3356
3357 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3358 {
3359 attributes |= UserDontExpirePasswrd;
3360 }
3361 break;
3362 case "RemoveOnUninstall":
3363 if (null == componentId)
3364 {
3365 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3366 }
3367
3368 if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3369 {
3370 attributes |= UserDontRemoveOnUninstall;
3371 }
3372 break;
3373 case "UpdateIfExists":
3374 if (null == componentId)
3375 {
3376 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3377 }
3378
3379 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3380 {
3381 attributes |= UserUpdateIfExists;
3382 }
3383 break;
3384 case "Vital":
3385 if (null == componentId)
3386 {
3387 this.Messaging.Write(UtilErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
3388 }
3389
3390 if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3391 {
3392 attributes |= UserNonVital;
3393 }
3394 break;
3395 default:
3396 this.ParseHelper.UnexpectedAttribute(element, attrib);
3397 break;
3398 }
3399 }
3400 else
3401 {
3402 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
3403 }
3404 }
3405
3406 if (null == id)
3407 {
3408 id = this.ParseHelper.CreateIdentifier("usr", componentId, name);
3409 }
3410
3411 if (null == name)
3412 {
3413 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
3414 }
3415
3416 foreach (var child in element.Elements())
3417 {
3418 if (this.Namespace == child.Name.Namespace)
3419 {
3420 switch (child.Name.LocalName)
3421 {
3422 case "GroupRef":
3423 if (null == componentId)
3424 {
3425 var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
3426 this.Messaging.Write(UtilErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
3427 }
3428
3429 this.ParseGroupRefElement(intermediate, section, child, id.Id);
3430 break;
3431 default:
3432 this.ParseHelper.UnexpectedElement(element, child);
3433 break;
3434 }
3435 }
3436 else
3437 {
3438 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
3439 }
3440 }
3441
3442 if (null != componentId)
3443 {
3444 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureUsers", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
3445 }
3446
3447 if (!this.Messaging.EncounteredError)
3448 {
3449 section.AddSymbol(new UserSymbol(sourceLineNumbers, id)
3450 {
3451 ComponentRef = componentId,
3452 Name = name,
3453 Domain = domain,
3454 Password = password,
3455 Attributes = attributes,
3456 });
3457 }
3458 }
3459
3460 /// <summary>
3461 /// Parses a XmlFile element.
3462 /// </summary>
3463 /// <param name="element">Element to parse.</param>
3464 /// <param name="componentId">Identifier of parent component.</param>
3465 private void ParseXmlFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
3466 {
3467 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
3468 Identifier id = null;
3469 string file = null;
3470 string elementPath = null;
3471 string name = null;
3472 string value = null;
3473 int sequence = -1;
3474 int flags = 0;
3475
3476 foreach (var attrib in element.Attributes())
3477 {
3478 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
3479 {
3480 switch (attrib.Name.LocalName)
3481 {
3482 case "Action":
3483 var actionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3484 switch (actionValue)
3485 {
3486 case "createElement":
3487 flags |= 0x00000001; // XMLFILE_CREATE_ELEMENT
3488 break;
3489 case "deleteValue":
3490 flags |= 0x00000002; // XMLFILE_DELETE_VALUE
3491 break;
3492 case "bulkSetValue":
3493 flags |= 0x00000004; // XMLFILE_BULKWRITE_VALUE
3494 break;
3495 case "setValue":
3496 // no flag for set value since it's the default
3497 break;
3498 default:
3499 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Action", actionValue, "createElement", "deleteValue", "setValue", "bulkSetValue"));
3500 break;
3501 }
3502 break;
3503 case "SelectionLanguage":
3504 string selectionLanguage = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3505 switch (selectionLanguage)
3506 {
3507 case "XPath":
3508 flags |= 0x00000100; // XMLFILE_USE_XPATH
3509 break;
3510 case "XSLPattern":
3511 // no flag for since it's the default
3512 break;
3513 default:
3514 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "SelectionLanguage", selectionLanguage, "XPath", "XSLPattern"));
3515 break;
3516 }
3517 break;
3518 case "Id":
3519 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
3520 break;
3521 case "File":
3522 file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3523 break;
3524 case "ElementPath":
3525 elementPath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3526 break;
3527 case "Name":
3528 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3529 break;
3530 case "Permanent":
3531 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3532 {
3533 flags |= 0x00010000; // XMLFILE_DONT_UNINSTALL
3534 }
3535 break;
3536 case "Sequence":
3537 sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int16.MaxValue);
3538 break;
3539 case "Value":
3540 value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3541 break;
3542 case "PreserveModifiedDate":
3543 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3544 {
3545 flags |= 0x00001000; // XMLFILE_PRESERVE_MODIFIED
3546 }
3547 break;
3548 default:
3549 this.ParseHelper.UnexpectedAttribute(element, attrib);
3550 break;
3551 }
3552 }
3553 else
3554 {
3555 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
3556 }
3557 }
3558
3559 if (null == id)
3560 {
3561 id = this.ParseHelper.CreateIdentifier("uxf", componentId, file, elementPath, name);
3562 }
3563
3564 if (null == file)
3565 {
3566 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File"));
3567 }
3568
3569 if (null == elementPath)
3570 {
3571 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ElementPath"));
3572 }
3573
3574 if ((0x00000001 /*XMLFILE_CREATE_ELEMENT*/ & flags) != 0 && null == name)
3575 {
3576 this.Messaging.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, element.Name.LocalName, "Action", "Name"));
3577 }
3578
3579 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
3580
3581 if (!this.Messaging.EncounteredError)
3582 {
3583 var symbol = section.AddSymbol(new XmlFileSymbol(sourceLineNumbers, id)
3584 {
3585 File = file,
3586 ElementPath = elementPath,
3587 Name = name,
3588 Value = value,
3589 Flags = flags,
3590 ComponentRef = componentId,
3591 });
3592 if (-1 != sequence)
3593 {
3594 symbol.Sequence = sequence;
3595 }
3596 }
3597
3598 this.AddReferenceToSchedXmlFile(sourceLineNumbers, section);
3599 }
3600
3601 /// <summary>
3602 /// Parses a XmlConfig element.
3603 /// </summary>
3604 /// <param name="element">Element to parse.</param>
3605 /// <param name="componentId">Identifier of parent component.</param>
3606 /// <param name="nested">Whether or not the element is nested.</param>
3607 private void ParseXmlConfigElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, bool nested)
3608 {
3609 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
3610 Identifier id = null;
3611 string elementId = null;
3612 string elementPath = null;
3613 int flags = 0;
3614 string file = null;
3615 string name = null;
3616 var sequence = CompilerConstants.IntegerNotSet;
3617 string value = null;
3618 string verifyPath = null;
3619
3620 foreach (var attrib in element.Attributes())
3621 {
3622 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
3623 {
3624 switch (attrib.Name.LocalName)
3625 {
3626 case "Id":
3627 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
3628 break;
3629 case "Action":
3630 if (nested)
3631 {
3632 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName));
3633 }
3634 else
3635 {
3636 string actionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3637 switch (actionValue)
3638 {
3639 case "create":
3640 flags |= 0x10; // XMLCONFIG_CREATE
3641 break;
3642 case "delete":
3643 flags |= 0x20; // XMLCONFIG_DELETE
3644 break;
3645 default:
3646 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, actionValue, "create", "delete"));
3647 break;
3648 }
3649 }
3650 break;
3651 case "ElementId":
3652 elementId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3653 break;
3654 case "ElementPath":
3655 elementPath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3656 break;
3657 case "File":
3658 file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3659 break;
3660 case "Name":
3661 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3662 break;
3663 case "Node":
3664 if (nested)
3665 {
3666 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName));
3667 }
3668 else
3669 {
3670 var nodeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3671 switch (nodeValue)
3672 {
3673 case "element":
3674 flags |= 0x1; // XMLCONFIG_ELEMENT
3675 break;
3676 case "value":
3677 flags |= 0x2; // XMLCONFIG_VALUE
3678 break;
3679 case "document":
3680 flags |= 0x4; // XMLCONFIG_DOCUMENT
3681 break;
3682 default:
3683 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, nodeValue, "element", "value", "document"));
3684 break;
3685 }
3686 }
3687 break;
3688 case "On":
3689 if (nested)
3690 {
3691 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName));
3692 }
3693 else
3694 {
3695 var onValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3696 switch (onValue)
3697 {
3698 case "install":
3699 flags |= 0x100; // XMLCONFIG_INSTALL
3700 break;
3701 case "uninstall":
3702 flags |= 0x200; // XMLCONFIG_UNINSTALL
3703 break;
3704 default:
3705 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, onValue, "install", "uninstall"));
3706 break;
3707 }
3708 }
3709 break;
3710 case "PreserveModifiedDate":
3711 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
3712 {
3713 flags |= 0x00001000; // XMLCONFIG_PRESERVE_MODIFIED
3714 }
3715 break;
3716 case "Sequence":
3717 sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int16.MaxValue);
3718 break;
3719 case "Value":
3720 value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3721 break;
3722 case "VerifyPath":
3723 verifyPath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
3724 break;
3725 default:
3726 this.ParseHelper.UnexpectedAttribute(element, attrib);
3727 break;
3728 }
3729 }
3730 else
3731 {
3732 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
3733 }
3734 }
3735
3736 if (null == id)
3737 {
3738 id = this.ParseHelper.CreateIdentifier("uxc", componentId, file, elementId, elementPath);
3739 }
3740
3741 if (null == file)
3742 {
3743 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File"));
3744 }
3745
3746 if (null == elementId && null == elementPath)
3747 {
3748 this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "ElementId", "ElementPath"));
3749 }
3750 else if (null != elementId)
3751 {
3752 if (null != elementPath)
3753 {
3754 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "ElementId", "ElementPath"));
3755 }
3756
3757 if (0 != flags)
3758 {
3759 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, "ElementId", "Action", "Node", "On"));
3760 }
3761
3762 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.XmlConfig, elementId);
3763 }
3764
3765 // find unexpected child elements
3766 foreach (var child in element.Elements())
3767 {
3768 if (this.Namespace == child.Name.Namespace)
3769 {
3770 switch (child.Name.LocalName)
3771 {
3772 case "XmlConfig":
3773 if (nested)
3774 {
3775 this.Messaging.Write(ErrorMessages.UnexpectedElement(sourceLineNumbers, element.Name.LocalName, child.Name.LocalName));
3776 }
3777 else
3778 {
3779 this.ParseXmlConfigElement(intermediate, section, child, componentId, true);
3780 }
3781 break;
3782 default:
3783 this.ParseHelper.UnexpectedElement(element, child);
3784 break;
3785 }
3786 }
3787 else
3788 {
3789 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
3790 }
3791 }
3792
3793 if (!this.Messaging.EncounteredError)
3794 {
3795 var symbol = section.AddSymbol(new XmlConfigSymbol(sourceLineNumbers, id)
3796 {
3797 File = file,
3798 ElementId = elementId,
3799 ElementPath = elementPath,
3800 VerifyPath = verifyPath,
3801 Name = name,
3802 Value = value,
3803 Flags = flags,
3804 ComponentRef = componentId,
3805 });
3806
3807 if (CompilerConstants.IntegerNotSet != sequence)
3808 {
3809 symbol.Sequence = sequence;
3810 }
3811 }
3812
3813 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedXmlConfig", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
3814 }
3815
3816 /// <summary>
3817 /// Match evaluator to escape properties in a string.
3818 /// </summary>
3819 private string EscapeProperties(Match match)
3820 {
3821 string escape = null;
3822 switch (match.Value)
3823 {
3824 case "[":
3825 escape = @"[\[]";
3826 break;
3827 case "]":
3828 escape = @"[\]]";
3829 break;
3830 }
3831
3832 return escape;
3833 }
3834
3835 private int CreateIntegerFromBitArray(BitArray bits)
3836 {
3837 if (32 != bits.Length)
3838 {
3839 throw new ArgumentException(String.Format("Can only convert a bit array with 32-bits to integer. Actual number of bits in array: {0}", bits.Length), "bits");
3840 }
3841
3842 var intArray = new int[1];
3843 bits.CopyTo(intArray, 0);
3844
3845 return intArray[0];
3846 }
3847
3848 private bool TrySetBitFromName(string[] attributeNames, string attributeName, YesNoType attributeValue, BitArray bits, int offset)
3849 {
3850 for (var i = 0; i < attributeNames.Length; i++)
3851 {
3852 if (attributeName.Equals(attributeNames[i], StringComparison.Ordinal))
3853 {
3854 bits.Set(i + offset, YesNoType.Yes == attributeValue);
3855 return true;
3856 }
3857 }
3858
3859 return false;
3860 }
3861
3862 private void AddReferenceToSchedXmlFile(SourceLineNumber sourceLineNumbers, IntermediateSection section)
3863 {
3864 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedXmlFile", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
3865 }
3866
3867 /// <summary>
3868 /// Private class that stores the data from a parsed PerformanceCounter element.
3869 /// </summary>
3870 private class ParsedPerformanceCounter
3871 {
3872 internal ParsedPerformanceCounter(string name, string help, System.Diagnostics.PerformanceCounterType type, int language)
3873 {
3874 this.Name = name;
3875 this.Help = help;
3876 this.Type = (int)type;
3877 this.Language = language.ToString("D3", CultureInfo.InvariantCulture);
3878 }
3879
3880 internal string Name { get; }
3881
3882 internal string Help { get; }
3883
3884 internal int Type { get; }
3885
3886 internal string Language { get; }
3887 }
3888 }
3889}
diff --git a/src/ext/Util/wixext/UtilConstants.cs b/src/ext/Util/wixext/UtilConstants.cs
new file mode 100644
index 00000000..28ff368f
--- /dev/null
+++ b/src/ext/Util/wixext/UtilConstants.cs
@@ -0,0 +1,17 @@
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.Util
4{
5 /// <summary>
6 /// Constants used by Utility Extension.
7 /// </summary>
8 internal static class UtilConstants
9 {
10 internal static readonly string[] FilePermissions = { "Read", "Write", "Append", "ReadExtendedAttributes", "WriteExtendedAttributes", "Execute", null, "ReadAttributes", "WriteAttributes" };
11 internal static readonly string[] FolderPermissions = { "Read", "CreateFile", "CreateChild", "ReadExtendedAttributes", "WriteExtendedAttributes", "Traverse", "DeleteChild", "ReadAttributes", "WriteAttributes" };
12 internal static readonly string[] GenericPermissions = { "GenericAll", "GenericExecute", "GenericWrite", "GenericRead" };
13 internal static readonly string[] RegistryPermissions = { "Read", "Write", "CreateSubkeys", "EnumerateSubkeys", "Notify", "CreateLink" };
14 internal static readonly string[] ServicePermissions = { "ServiceQueryConfig", "ServiceChangeConfig", "ServiceQueryStatus", "ServiceEnumerateDependents", "ServiceStart", "ServiceStop", "ServicePauseContinue", "ServiceInterrogate", "ServiceUserDefinedControl" };
15 internal static readonly string[] StandardPermissions = { "Delete", "ReadPermission", "ChangePermission", "TakeOwnership", "Synchronize" };
16 }
17}
diff --git a/src/ext/Util/wixext/UtilDecompiler.cs b/src/ext/Util/wixext/UtilDecompiler.cs
new file mode 100644
index 00000000..9ef3390f
--- /dev/null
+++ b/src/ext/Util/wixext/UtilDecompiler.cs
@@ -0,0 +1,1543 @@
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.Extensions
4{
5#if TODO_CONSIDER_DECOMPILER
6 using System;
7 using System.IO;
8 using System.Text;
9 using System.Collections;
10 using System.Diagnostics;
11 using System.Globalization;
12
13 using Util = WixToolset.Extensions.Serialize.Util;
14 using WixToolset.Data;
15 using WixToolset.Extensibility;
16 using Wix = WixToolset.Data.Serialize;
17
18 /// <summary>
19 /// The decompiler for the WiX Toolset Utility Extension.
20 /// </summary>
21 public sealed class UtilDecompiler : DecompilerExtension
22 {
23 /// <summary>
24 /// Creates a decompiler for Utility Extension.
25 /// </summary>
26 public UtilDecompiler()
27 {
28 this.TableDefinitions = UtilExtensionData.GetExtensionTableDefinitions();
29 }
30
31 /// <summary>
32 /// Get the extensions library to be removed.
33 /// </summary>
34 /// <param name="tableDefinitions">Table definitions for library.</param>
35 /// <returns>Library to remove from decompiled output.</returns>
36 public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
37 {
38 return UtilExtensionData.GetExtensionLibrary(tableDefinitions);
39 }
40
41 /// <summary>
42 /// Called at the beginning of the decompilation of a database.
43 /// </summary>
44 /// <param name="tables">The collection of all tables.</param>
45 public override void Initialize(TableIndexedCollection tables)
46 {
47 this.CleanupSecureCustomProperties(tables);
48 this.CleanupInternetShortcutRemoveFileTables(tables);
49 }
50
51 /// <summary>
52 /// Decompile the SecureCustomProperties field to PropertyRefs for known extension properties.
53 /// </summary>
54 /// <remarks>
55 /// If we've referenced any of the suite or directory properties, add
56 /// a PropertyRef to refer to the Property (and associated custom action)
57 /// from the extension's library. Then remove the property from
58 /// SecureCustomExtensions property so later decompilation won't create
59 /// new Property elements.
60 /// </remarks>
61 /// <param name="tables">The collection of all tables.</param>
62 private void CleanupSecureCustomProperties(TableIndexedCollection tables)
63 {
64 Table propertyTable = tables["Property"];
65
66 if (null != propertyTable)
67 {
68 foreach (Row row in propertyTable.Rows)
69 {
70 if ("SecureCustomProperties" == row[0].ToString())
71 {
72 StringBuilder remainingProperties = new StringBuilder();
73 string[] secureCustomProperties = row[1].ToString().Split(';');
74 foreach (string property in secureCustomProperties)
75 {
76 if (property.StartsWith("WIX_SUITE_", StringComparison.Ordinal) || property.StartsWith("WIX_DIR_", StringComparison.Ordinal)
77 || property.StartsWith("WIX_ACCOUNT_", StringComparison.Ordinal))
78 {
79 Wix.PropertyRef propertyRef = new Wix.PropertyRef();
80 propertyRef.Id = property;
81 this.Core.RootElement.AddChild(propertyRef);
82 }
83 else
84 {
85 if (0 < remainingProperties.Length)
86 {
87 remainingProperties.Append(";");
88 }
89 remainingProperties.Append(property);
90 }
91 }
92
93 row[1] = remainingProperties.ToString();
94 break;
95 }
96 }
97 }
98 }
99
100 /// <summary>
101 /// Remove RemoveFile rows that the InternetShortcut compiler extension adds for us.
102 /// </summary>
103 /// <param name="tables">The collection of all tables.</param>
104 private void CleanupInternetShortcutRemoveFileTables(TableIndexedCollection tables)
105 {
106 // index the WixInternetShortcut table
107 Table wixInternetShortcutTable = tables["WixInternetShortcut"];
108 Hashtable wixInternetShortcuts = new Hashtable();
109 if (null != wixInternetShortcutTable)
110 {
111 foreach (Row row in wixInternetShortcutTable.Rows)
112 {
113 wixInternetShortcuts.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row);
114 }
115 }
116
117 // remove the RemoveFile rows with primary keys that match the WixInternetShortcut table's
118 Table removeFileTable = tables["RemoveFile"];
119 if (null != removeFileTable)
120 {
121 for (int i = removeFileTable.Rows.Count - 1; 0 <= i; i--)
122 {
123 if (null != wixInternetShortcuts[removeFileTable.Rows[i][0]])
124 {
125 removeFileTable.Rows.RemoveAt(i);
126 }
127 }
128 }
129 }
130
131 /// <summary>
132 /// Decompiles an extension table.
133 /// </summary>
134 /// <param name="table">The table to decompile.</param>
135 public override void DecompileTable(Table table)
136 {
137 switch (table.Name)
138 {
139 case "WixCloseApplication":
140 this.DecompileWixCloseApplicationTable(table);
141 break;
142 case "WixRemoveFolderEx":
143 this.DecompileWixRemoveFolderExTable(table);
144 break;
145 case "WixRestartResource":
146 this.DecompileWixRestartResourceTable(table);
147 break;
148 case "FileShare":
149 this.DecompileFileShareTable(table);
150 break;
151 case "FileSharePermissions":
152 this.DecompileFileSharePermissionsTable(table);
153 break;
154 case "WixInternetShortcut":
155 this.DecompileWixInternetShortcutTable(table);
156 break;
157 case "Group":
158 this.DecompileGroupTable(table);
159 break;
160 case "Perfmon":
161 this.DecompilePerfmonTable(table);
162 break;
163 case "PerfmonManifest":
164 this.DecompilePerfmonManifestTable(table);
165 break;
166 case "EventManifest":
167 this.DecompileEventManifestTable(table);
168 break;
169 case "SecureObjects":
170 this.DecompileSecureObjectsTable(table);
171 break;
172 case "ServiceConfig":
173 this.DecompileServiceConfigTable(table);
174 break;
175 case "User":
176 this.DecompileUserTable(table);
177 break;
178 case "UserGroup":
179 this.DecompileUserGroupTable(table);
180 break;
181 case "XmlConfig":
182 this.DecompileXmlConfigTable(table);
183 break;
184 case "XmlFile":
185 // XmlFile decompilation has been moved to FinalizeXmlFileTable function
186 break;
187 default:
188 base.DecompileTable(table);
189 break;
190 }
191 }
192
193 /// <summary>
194 /// Finalize decompilation.
195 /// </summary>
196 /// <param name="tables">The collection of all tables.</param>
197 public override void Finish(TableIndexedCollection tables)
198 {
199 this.FinalizePerfmonTable(tables);
200 this.FinalizePerfmonManifestTable(tables);
201 this.FinalizeSecureObjectsTable(tables);
202 this.FinalizeServiceConfigTable(tables);
203 this.FinalizeXmlConfigTable(tables);
204 this.FinalizeXmlFileTable(tables);
205 this.FinalizeEventManifestTable(tables);
206 }
207
208 /// <summary>
209 /// Decompile the WixCloseApplication table.
210 /// </summary>
211 /// <param name="table">The table to decompile.</param>
212 private void DecompileWixCloseApplicationTable(Table table)
213 {
214 foreach (Row row in table.Rows)
215 {
216 Util.CloseApplication closeApplication = new Util.CloseApplication();
217
218 closeApplication.Id = (string)row[0];
219
220 closeApplication.Target = (string)row[1];
221
222 if (null != row[2])
223 {
224 closeApplication.Description = (string)row[2];
225 }
226
227 if (null != row[3])
228 {
229 closeApplication.Content = (string)row[3];
230 }
231
232 // set defaults
233 closeApplication.CloseMessage = Util.YesNoType.no;
234 closeApplication.RebootPrompt = Util.YesNoType.yes;
235 closeApplication.ElevatedCloseMessage = Util.YesNoType.no;
236
237 if (null != row[4])
238 {
239 int attribute = (int)row[4];
240
241 closeApplication.CloseMessage = (0x1 == (attribute & 0x1)) ? Util.YesNoType.yes : Util.YesNoType.no;
242 closeApplication.RebootPrompt = (0x2 == (attribute & 0x2)) ? Util.YesNoType.yes : Util.YesNoType.no;
243 closeApplication.ElevatedCloseMessage = (0x4 == (attribute & 0x4)) ? Util.YesNoType.yes : Util.YesNoType.no;
244 }
245
246 if (null != row[5])
247 {
248 closeApplication.Sequence = (int)row[5];
249 }
250
251 if (null != row[6])
252 {
253 closeApplication.Property = (string)row[6];
254 }
255
256 this.Core.RootElement.AddChild(closeApplication);
257 }
258 }
259
260 /// <summary>
261 /// Decompile the WixRemoveFolderEx table.
262 /// </summary>
263 /// <param name="table">The table to decompile.</param>
264 private void DecompileWixRemoveFolderExTable(Table table)
265 {
266 foreach (Row row in table.Rows)
267 {
268 // Set the Id even if auto-generated previously.
269 Util.RemoveFolderEx removeFolder = new Util.RemoveFolderEx();
270 removeFolder.Id = (string)row[0];
271 removeFolder.Property = (string)row[2];
272
273 int installMode = (int)row[3];
274 switch ((UtilCompiler.WixRemoveFolderExOn)installMode)
275 {
276 case UtilCompiler.WixRemoveFolderExOn.Install:
277 removeFolder.On = Util.RemoveFolderEx.OnType.install;
278 break;
279
280 case UtilCompiler.WixRemoveFolderExOn.Uninstall:
281 removeFolder.On = Util.RemoveFolderEx.OnType.uninstall;
282 break;
283
284 case UtilCompiler.WixRemoveFolderExOn.Both:
285 removeFolder.On = Util.RemoveFolderEx.OnType.both;
286 break;
287
288 default:
289 this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "InstallMode", installMode));
290 break;
291 }
292
293 // Add to the appropriate Component or section element.
294 string componentId = (string)row[1];
295 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId);
296 if (null != component)
297 {
298 component.AddChild(removeFolder);
299 }
300 else
301 {
302 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", componentId, "Component"));
303 }
304 }
305 }
306
307 /// <summary>
308 /// Decompile the WixRestartResource table.
309 /// </summary>
310 /// <param name="table">The table to decompile.</param>
311 private void DecompileWixRestartResourceTable(Table table)
312 {
313 foreach (Row row in table.Rows)
314 {
315 // Set the Id even if auto-generated previously.
316 Util.RestartResource restartResource = new Util.RestartResource();
317 restartResource.Id = (string)row[0];
318
319 // Determine the resource type and set accordingly.
320 string resource = (string)row[2];
321 int attributes = (int)row[3];
322 UtilCompiler.WixRestartResourceAttributes type = (UtilCompiler.WixRestartResourceAttributes)(attributes & (int)UtilCompiler.WixRestartResourceAttributes.TypeMask);
323
324 switch (type)
325 {
326 case UtilCompiler.WixRestartResourceAttributes.Filename:
327 restartResource.Path = resource;
328 break;
329
330 case UtilCompiler.WixRestartResourceAttributes.ProcessName:
331 restartResource.ProcessName = resource;
332 break;
333
334 case UtilCompiler.WixRestartResourceAttributes.ServiceName:
335 restartResource.ServiceName = resource;
336 break;
337
338 default:
339 this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Attributes", attributes));
340 break;
341 }
342
343 // Add to the appropriate Component or section element.
344 string componentId = (string)row[1];
345 if (!String.IsNullOrEmpty(componentId))
346 {
347 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId);
348 if (null != component)
349 {
350 component.AddChild(restartResource);
351 }
352 else
353 {
354 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", componentId, "Component"));
355 }
356 }
357 else
358 {
359 this.Core.RootElement.AddChild(restartResource);
360 }
361 }
362 }
363
364 /// <summary>
365 /// Decompile the FileShare table.
366 /// </summary>
367 /// <param name="table">The table to decompile.</param>
368 private void DecompileFileShareTable(Table table)
369 {
370 foreach (Row row in table.Rows)
371 {
372 Util.FileShare fileShare = new Util.FileShare();
373
374 fileShare.Id = (string)row[0];
375
376 fileShare.Name = (string)row[1];
377
378 if (null != row[3])
379 {
380 fileShare.Description = (string)row[3];
381 }
382
383 // the Directory_ column is set by the parent Component
384
385 // the User_ and Permissions columns are deprecated
386
387 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
388 if (null != component)
389 {
390 component.AddChild(fileShare);
391 }
392 else
393 {
394 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
395 }
396 this.Core.IndexElement(row, fileShare);
397 }
398 }
399
400 /// <summary>
401 /// Decompile the FileSharePermissions table.
402 /// </summary>
403 /// <param name="table">The table to decompile.</param>
404 private void DecompileFileSharePermissionsTable(Table table)
405 {
406 foreach (Row row in table.Rows)
407 {
408 Util.FileSharePermission fileSharePermission = new Util.FileSharePermission();
409
410 fileSharePermission.User = (string)row[1];
411
412 string[] specialPermissions = UtilConstants.FolderPermissions;
413 int permissions = (int)row[2];
414 for (int i = 0; i < 32; i++)
415 {
416 if (0 != ((permissions >> i) & 1))
417 {
418 string name = null;
419
420 if (16 > i && specialPermissions.Length > i)
421 {
422 name = specialPermissions[i];
423 }
424 else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16))
425 {
426 name = UtilConstants.StandardPermissions[i - 16];
427 }
428 else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28))
429 {
430 name = UtilConstants.GenericPermissions[i - 28];
431 }
432
433 if (null == name)
434 {
435 this.Core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i));
436 }
437 else
438 {
439 switch (name)
440 {
441 case "ChangePermission":
442 fileSharePermission.ChangePermission = Util.YesNoType.yes;
443 break;
444 case "CreateChild":
445 fileSharePermission.CreateChild = Util.YesNoType.yes;
446 break;
447 case "CreateFile":
448 fileSharePermission.CreateFile = Util.YesNoType.yes;
449 break;
450 case "Delete":
451 fileSharePermission.Delete = Util.YesNoType.yes;
452 break;
453 case "DeleteChild":
454 fileSharePermission.DeleteChild = Util.YesNoType.yes;
455 break;
456 case "GenericAll":
457 fileSharePermission.GenericAll = Util.YesNoType.yes;
458 break;
459 case "GenericExecute":
460 fileSharePermission.GenericExecute = Util.YesNoType.yes;
461 break;
462 case "GenericRead":
463 fileSharePermission.GenericRead = Util.YesNoType.yes;
464 break;
465 case "GenericWrite":
466 fileSharePermission.GenericWrite = Util.YesNoType.yes;
467 break;
468 case "Read":
469 fileSharePermission.Read = Util.YesNoType.yes;
470 break;
471 case "ReadAttributes":
472 fileSharePermission.ReadAttributes = Util.YesNoType.yes;
473 break;
474 case "ReadExtendedAttributes":
475 fileSharePermission.ReadExtendedAttributes = Util.YesNoType.yes;
476 break;
477 case "ReadPermission":
478 fileSharePermission.ReadPermission = Util.YesNoType.yes;
479 break;
480 case "Synchronize":
481 fileSharePermission.Synchronize = Util.YesNoType.yes;
482 break;
483 case "TakeOwnership":
484 fileSharePermission.TakeOwnership = Util.YesNoType.yes;
485 break;
486 case "Traverse":
487 fileSharePermission.Traverse = Util.YesNoType.yes;
488 break;
489 case "WriteAttributes":
490 fileSharePermission.WriteAttributes = Util.YesNoType.yes;
491 break;
492 case "WriteExtendedAttributes":
493 fileSharePermission.WriteExtendedAttributes = Util.YesNoType.yes;
494 break;
495 default:
496 Debug.Fail(String.Format("Unknown permission '{0}'.", name));
497 break;
498 }
499 }
500 }
501 }
502
503 Util.FileShare fileShare = (Util.FileShare)this.Core.GetIndexedElement("FileShare", (string)row[0]);
504 if (null != fileShare)
505 {
506 fileShare.AddChild(fileSharePermission);
507 }
508 else
509 {
510 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileShare_", (string)row[0], "FileShare"));
511 }
512 }
513 }
514
515 /// <summary>
516 /// Decompile the Group table.
517 /// </summary>
518 /// <param name="table">The table to decompile.</param>
519 private void DecompileGroupTable(Table table)
520 {
521 foreach (Row row in table.Rows)
522 {
523 Util.Group group = new Util.Group();
524
525 group.Id = (string)row[0];
526
527 if (null != row[1])
528 {
529 this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Component_", (string)row[1]));
530 }
531
532 group.Name = (string)row[2];
533
534 if (null != row[3])
535 {
536 group.Domain = (string)row[3];
537 }
538
539 this.Core.RootElement.AddChild(group);
540 }
541 }
542
543 /// <summary>
544 /// Decompile the WixInternetShortcut table.
545 /// </summary>
546 /// <param name="table">The table to decompile.</param>
547 private void DecompileWixInternetShortcutTable(Table table)
548 {
549 foreach (Row row in table.Rows)
550 {
551 Util.InternetShortcut internetShortcut = new Util.InternetShortcut();
552 internetShortcut.Id = (string)row[0];
553 internetShortcut.Directory = (string)row[2];
554 // remove .lnk/.url extension because compiler extension adds it back for us
555 internetShortcut.Name = Path.ChangeExtension((string)row[3], null);
556 internetShortcut.Target = (string)row[4];
557 internetShortcut.IconFile = (string)row[6];
558 internetShortcut.IconIndex = (int)row[7];
559
560 UtilCompiler.InternetShortcutType shortcutType = (UtilCompiler.InternetShortcutType)row[5];
561 switch (shortcutType)
562 {
563 case UtilCompiler.InternetShortcutType.Link:
564 internetShortcut.Type = Util.InternetShortcut.TypeType.link;
565 break;
566 case UtilCompiler.InternetShortcutType.Url:
567 internetShortcut.Type = Util.InternetShortcut.TypeType.url;
568 break;
569 }
570
571 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
572 if (null != component)
573 {
574 component.AddChild(internetShortcut);
575 }
576 else
577 {
578 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
579 }
580
581 this.Core.IndexElement(row, internetShortcut);
582 }
583 }
584
585 /// <summary>
586 /// Decompile the Perfmon table.
587 /// </summary>
588 /// <param name="table">The table to decompile.</param>
589 private void DecompilePerfmonTable(Table table)
590 {
591 foreach (Row row in table.Rows)
592 {
593 Util.PerfCounter perfCounter = new Util.PerfCounter();
594
595 perfCounter.Name = (string)row[2];
596
597 this.Core.IndexElement(row, perfCounter);
598 }
599 }
600
601 /// <summary>
602 /// Decompile the PerfmonManifest table.
603 /// </summary>
604 /// <param name="table">The table to decompile.</param>
605 private void DecompilePerfmonManifestTable(Table table)
606 {
607 foreach (Row row in table.Rows)
608 {
609 Util.PerfCounterManifest perfCounterManifest = new Util.PerfCounterManifest();
610
611 perfCounterManifest.ResourceFileDirectory = (string)row[2];
612
613 this.Core.IndexElement(row, perfCounterManifest);
614 }
615 }
616
617 /// <summary>
618 /// Decompile the EventManifest table.
619 /// </summary>
620 /// <param name="table">The table to decompile.</param>
621 private void DecompileEventManifestTable(Table table)
622 {
623 foreach (Row row in table.Rows)
624 {
625 Util.EventManifest eventManifest = new Util.EventManifest();
626 this.Core.IndexElement(row, eventManifest);
627 }
628 }
629
630 /// <summary>
631 /// Decompile the SecureObjects table.
632 /// </summary>
633 /// <param name="table">The table to decompile.</param>
634 private void DecompileSecureObjectsTable(Table table)
635 {
636 foreach (Row row in table.Rows)
637 {
638 Util.PermissionEx permissionEx = new Util.PermissionEx();
639
640 string[] specialPermissions;
641 switch ((string)row[1])
642 {
643 case "CreateFolder":
644 specialPermissions = UtilConstants.FolderPermissions;
645 break;
646 case "File":
647 specialPermissions = UtilConstants.FilePermissions;
648 break;
649 case "Registry":
650 specialPermissions = UtilConstants.RegistryPermissions;
651 break;
652 case "ServiceInstall":
653 specialPermissions = UtilConstants.ServicePermissions;
654 break;
655 default:
656 this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, row.Table.Name, row.Fields[1].Column.Name, row[1]));
657 return;
658 }
659
660 int permissionBits = (int)row[4];
661 for (int i = 0; i < 32; i++)
662 {
663 if (0 != ((permissionBits >> i) & 1))
664 {
665 string name = null;
666
667 if (16 > i && specialPermissions.Length > i)
668 {
669 name = specialPermissions[i];
670 }
671 else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16))
672 {
673 name = UtilConstants.StandardPermissions[i - 16];
674 }
675 else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28))
676 {
677 name = UtilConstants.GenericPermissions[i - 28];
678 }
679
680 if (null == name)
681 {
682 this.Core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i));
683 }
684 else
685 {
686 switch (name)
687 {
688 case "Append":
689 permissionEx.Append = Util.YesNoType.yes;
690 break;
691 case "ChangePermission":
692 permissionEx.ChangePermission = Util.YesNoType.yes;
693 break;
694 case "CreateChild":
695 permissionEx.CreateChild = Util.YesNoType.yes;
696 break;
697 case "CreateFile":
698 permissionEx.CreateFile = Util.YesNoType.yes;
699 break;
700 case "CreateLink":
701 permissionEx.CreateLink = Util.YesNoType.yes;
702 break;
703 case "CreateSubkeys":
704 permissionEx.CreateSubkeys = Util.YesNoType.yes;
705 break;
706 case "Delete":
707 permissionEx.Delete = Util.YesNoType.yes;
708 break;
709 case "DeleteChild":
710 permissionEx.DeleteChild = Util.YesNoType.yes;
711 break;
712 case "EnumerateSubkeys":
713 permissionEx.EnumerateSubkeys = Util.YesNoType.yes;
714 break;
715 case "Execute":
716 permissionEx.Execute = Util.YesNoType.yes;
717 break;
718 case "GenericAll":
719 permissionEx.GenericAll = Util.YesNoType.yes;
720 break;
721 case "GenericExecute":
722 permissionEx.GenericExecute = Util.YesNoType.yes;
723 break;
724 case "GenericRead":
725 permissionEx.GenericRead = Util.YesNoType.yes;
726 break;
727 case "GenericWrite":
728 permissionEx.GenericWrite = Util.YesNoType.yes;
729 break;
730 case "Notify":
731 permissionEx.Notify = Util.YesNoType.yes;
732 break;
733 case "Read":
734 permissionEx.Read = Util.YesNoType.yes;
735 break;
736 case "ReadAttributes":
737 permissionEx.ReadAttributes = Util.YesNoType.yes;
738 break;
739 case "ReadExtendedAttributes":
740 permissionEx.ReadExtendedAttributes = Util.YesNoType.yes;
741 break;
742 case "ReadPermission":
743 permissionEx.ReadPermission = Util.YesNoType.yes;
744 break;
745 case "ServiceChangeConfig":
746 permissionEx.ServiceChangeConfig = Util.YesNoType.yes;
747 break;
748 case "ServiceEnumerateDependents":
749 permissionEx.ServiceEnumerateDependents = Util.YesNoType.yes;
750 break;
751 case "ServiceInterrogate":
752 permissionEx.ServiceInterrogate = Util.YesNoType.yes;
753 break;
754 case "ServicePauseContinue":
755 permissionEx.ServicePauseContinue = Util.YesNoType.yes;
756 break;
757 case "ServiceQueryConfig":
758 permissionEx.ServiceQueryConfig = Util.YesNoType.yes;
759 break;
760 case "ServiceQueryStatus":
761 permissionEx.ServiceQueryStatus = Util.YesNoType.yes;
762 break;
763 case "ServiceStart":
764 permissionEx.ServiceStart = Util.YesNoType.yes;
765 break;
766 case "ServiceStop":
767 permissionEx.ServiceStop = Util.YesNoType.yes;
768 break;
769 case "ServiceUserDefinedControl":
770 permissionEx.ServiceUserDefinedControl = Util.YesNoType.yes;
771 break;
772 case "Synchronize":
773 permissionEx.Synchronize = Util.YesNoType.yes;
774 break;
775 case "TakeOwnership":
776 permissionEx.TakeOwnership = Util.YesNoType.yes;
777 break;
778 case "Traverse":
779 permissionEx.Traverse = Util.YesNoType.yes;
780 break;
781 case "Write":
782 permissionEx.Write = Util.YesNoType.yes;
783 break;
784 case "WriteAttributes":
785 permissionEx.WriteAttributes = Util.YesNoType.yes;
786 break;
787 case "WriteExtendedAttributes":
788 permissionEx.WriteExtendedAttributes = Util.YesNoType.yes;
789 break;
790 default:
791 throw new InvalidOperationException(String.Format("Unknown permission attribute '{0}'.", name));
792 }
793 }
794 }
795 }
796
797 if (null != row[2])
798 {
799 permissionEx.Domain = (string)row[2];
800 }
801
802 permissionEx.User = (string)row[3];
803
804 this.Core.IndexElement(row, permissionEx);
805 }
806 }
807
808 /// <summary>
809 /// Decompile the ServiceConfig table.
810 /// </summary>
811 /// <param name="table">The table to decompile.</param>
812 private void DecompileServiceConfigTable(Table table)
813 {
814 foreach (Row row in table.Rows)
815 {
816 Util.ServiceConfig serviceConfig = new Util.ServiceConfig();
817
818 serviceConfig.ServiceName = (string)row[0];
819
820 switch ((string)row[3])
821 {
822 case "none":
823 serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.none;
824 break;
825 case "reboot":
826 serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.reboot;
827 break;
828 case "restart":
829 serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.restart;
830 break;
831 case "runCommand":
832 serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.runCommand;
833 break;
834 default:
835 this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[3].Column.Name, row[3]));
836 break;
837 }
838
839 switch ((string)row[4])
840 {
841 case "none":
842 serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.none;
843 break;
844 case "reboot":
845 serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.reboot;
846 break;
847 case "restart":
848 serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.restart;
849 break;
850 case "runCommand":
851 serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.runCommand;
852 break;
853 default:
854 this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4]));
855 break;
856 }
857
858 switch ((string)row[5])
859 {
860 case "none":
861 serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.none;
862 break;
863 case "reboot":
864 serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.reboot;
865 break;
866 case "restart":
867 serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.restart;
868 break;
869 case "runCommand":
870 serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.runCommand;
871 break;
872 default:
873 this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[5].Column.Name, row[5]));
874 break;
875 }
876
877 if (null != row[6])
878 {
879 serviceConfig.ResetPeriodInDays = (int)row[6];
880 }
881
882 if (null != row[7])
883 {
884 serviceConfig.RestartServiceDelayInSeconds = (int)row[7];
885 }
886
887 if (null != row[8])
888 {
889 serviceConfig.ProgramCommandLine = (string)row[8];
890 }
891
892 if (null != row[9])
893 {
894 serviceConfig.RebootMessage = (string)row[9];
895 }
896
897 this.Core.IndexElement(row, serviceConfig);
898 }
899 }
900
901 /// <summary>
902 /// Decompile the User table.
903 /// </summary>
904 /// <param name="table">The table to decompile.</param>
905 private void DecompileUserTable(Table table)
906 {
907 foreach (Row row in table.Rows)
908 {
909 Util.User user = new Util.User();
910
911 user.Id = (string)row[0];
912
913 user.Name = (string)row[2];
914
915 if (null != row[3])
916 {
917 user.Domain = (string)row[3];
918 }
919
920 if (null != row[4])
921 {
922 user.Password = (string)row[4];
923 }
924
925 if (null != row[5])
926 {
927 int attributes = (int)row[5];
928
929 if (UtilCompiler.UserDontExpirePasswrd == (attributes & UtilCompiler.UserDontExpirePasswrd))
930 {
931 user.PasswordNeverExpires = Util.YesNoType.yes;
932 }
933
934 if (UtilCompiler.UserPasswdCantChange == (attributes & UtilCompiler.UserPasswdCantChange))
935 {
936 user.CanNotChangePassword = Util.YesNoType.yes;
937 }
938
939 if (UtilCompiler.UserPasswdChangeReqdOnLogin == (attributes & UtilCompiler.UserPasswdChangeReqdOnLogin))
940 {
941 user.PasswordExpired = Util.YesNoType.yes;
942 }
943
944 if (UtilCompiler.UserDisableAccount == (attributes & UtilCompiler.UserDisableAccount))
945 {
946 user.Disabled = Util.YesNoType.yes;
947 }
948
949 if (UtilCompiler.UserFailIfExists == (attributes & UtilCompiler.UserFailIfExists))
950 {
951 user.FailIfExists = Util.YesNoType.yes;
952 }
953
954 if (UtilCompiler.UserUpdateIfExists == (attributes & UtilCompiler.UserUpdateIfExists))
955 {
956 user.UpdateIfExists = Util.YesNoType.yes;
957 }
958
959 if (UtilCompiler.UserLogonAsService == (attributes & UtilCompiler.UserLogonAsService))
960 {
961 user.LogonAsService = Util.YesNoType.yes;
962 }
963
964 if (UtilCompiler.UserDontRemoveOnUninstall == (attributes & UtilCompiler.UserDontRemoveOnUninstall))
965 {
966 user.RemoveOnUninstall = Util.YesNoType.no;
967 }
968
969 if (UtilCompiler.UserDontCreateUser == (attributes & UtilCompiler.UserDontCreateUser))
970 {
971 user.CreateUser = Util.YesNoType.no;
972 }
973
974 if (UtilCompiler.UserNonVital == (attributes & UtilCompiler.UserNonVital))
975 {
976 user.Vital = Util.YesNoType.no;
977 }
978 }
979
980 if (null != row[1])
981 {
982 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
983
984 if (null != component)
985 {
986 component.AddChild(user);
987 }
988 else
989 {
990 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
991 }
992 }
993 else
994 {
995 this.Core.RootElement.AddChild(user);
996 }
997 this.Core.IndexElement(row, user);
998 }
999 }
1000
1001 /// <summary>
1002 /// Decompile the UserGroup table.
1003 /// </summary>
1004 /// <param name="table">The table to decompile.</param>
1005 private void DecompileUserGroupTable(Table table)
1006 {
1007 foreach (Row row in table.Rows)
1008 {
1009 Util.User user = (Util.User)this.Core.GetIndexedElement("User", (string)row[0]);
1010
1011 if (null != user)
1012 {
1013 Util.GroupRef groupRef = new Util.GroupRef();
1014
1015 groupRef.Id = (string)row[1];
1016
1017 user.AddChild(groupRef);
1018 }
1019 else
1020 {
1021 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Group_", (string)row[0], "Group"));
1022 }
1023 }
1024 }
1025
1026 /// <summary>
1027 /// Decompile the XmlConfig table.
1028 /// </summary>
1029 /// <param name="table">The table to decompile.</param>
1030 private void DecompileXmlConfigTable(Table table)
1031 {
1032 foreach (Row row in table.Rows)
1033 {
1034 Util.XmlConfig xmlConfig = new Util.XmlConfig();
1035
1036 xmlConfig.Id = (string)row[0];
1037
1038 xmlConfig.File = (string)row[1];
1039
1040 xmlConfig.ElementPath = (string)row[2];
1041
1042 if (null != row[3])
1043 {
1044 xmlConfig.VerifyPath = (string)row[3];
1045 }
1046
1047 if (null != row[4])
1048 {
1049 xmlConfig.Name = (string)row[4];
1050 }
1051
1052 if (null != row[5])
1053 {
1054 xmlConfig.Value = (string)row[5];
1055 }
1056
1057 int flags = (int)row[6];
1058
1059 if (0x1 == (flags & 0x1))
1060 {
1061 xmlConfig.Node = Util.XmlConfig.NodeType.element;
1062 }
1063 else if (0x2 == (flags & 0x2))
1064 {
1065 xmlConfig.Node = Util.XmlConfig.NodeType.value;
1066 }
1067 else if (0x4 == (flags & 0x4))
1068 {
1069 xmlConfig.Node = Util.XmlConfig.NodeType.document;
1070 }
1071
1072 if (0x10 == (flags & 0x10))
1073 {
1074 xmlConfig.Action = Util.XmlConfig.ActionType.create;
1075 }
1076 else if (0x20 == (flags & 0x20))
1077 {
1078 xmlConfig.Action = Util.XmlConfig.ActionType.delete;
1079 }
1080
1081 if (0x100 == (flags & 0x100))
1082 {
1083 xmlConfig.On = Util.XmlConfig.OnType.install;
1084 }
1085 else if (0x200 == (flags & 0x200))
1086 {
1087 xmlConfig.On = Util.XmlConfig.OnType.uninstall;
1088 }
1089
1090 if (0x00001000 == (flags & 0x00001000))
1091 {
1092 xmlConfig.PreserveModifiedDate = Util.YesNoType.yes;
1093 }
1094
1095 if (null != row[8])
1096 {
1097 xmlConfig.Sequence = (int)row[8];
1098 }
1099
1100 this.Core.IndexElement(row, xmlConfig);
1101 }
1102 }
1103
1104 /// <summary>
1105 /// Finalize the Perfmon table.
1106 /// </summary>
1107 /// <param name="tables">The collection of all tables.</param>
1108 /// <remarks>
1109 /// Since the PerfCounter element nests under a File element, but
1110 /// the Perfmon table does not have a foreign key relationship with
1111 /// the File table (instead it has a formatted string that usually
1112 /// refers to a file row - but doesn't have to), the nesting must
1113 /// be inferred during finalization.
1114 /// </remarks>
1115 private void FinalizePerfmonTable(TableIndexedCollection tables)
1116 {
1117 Table perfmonTable = tables["Perfmon"];
1118
1119 if (null != perfmonTable)
1120 {
1121 foreach (Row row in perfmonTable.Rows)
1122 {
1123 string formattedFile = (string)row[1];
1124 Util.PerfCounter perfCounter = (Util.PerfCounter)this.Core.GetIndexedElement(row);
1125
1126 // try to "de-format" the File column's value to determine the proper parent File element
1127 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
1128 && formattedFile.EndsWith("]", StringComparison.Ordinal))
1129 {
1130 string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1131
1132 Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId);
1133 if (null != file)
1134 {
1135 file.AddChild(perfCounter);
1136 }
1137 else
1138 {
1139 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfmonTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File", formattedFile, "File"));
1140 }
1141 }
1142 else
1143 {
1144 this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "Perfmon"));
1145 }
1146 }
1147 }
1148 }
1149
1150 /// <summary>
1151 /// Finalize the PerfmonManifest table.
1152 /// </summary>
1153 /// <param name="tables">The collection of all tables.</param>
1154 private void FinalizePerfmonManifestTable(TableIndexedCollection tables)
1155 {
1156 Table perfmonManifestTable = tables["PerfmonManifest"];
1157
1158 if (null != perfmonManifestTable)
1159 {
1160 foreach (Row row in perfmonManifestTable.Rows)
1161 {
1162 string formattedFile = (string)row[1];
1163 Util.PerfCounterManifest perfCounterManifest = (Util.PerfCounterManifest)this.Core.GetIndexedElement(row);
1164
1165 // try to "de-format" the File column's value to determine the proper parent File element
1166 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
1167 && formattedFile.EndsWith("]", StringComparison.Ordinal))
1168 {
1169 string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1170
1171 Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId);
1172 if (null != file)
1173 {
1174 file.AddChild(perfCounterManifest);
1175 }
1176 else
1177 {
1178 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfCounterManifest.ResourceFileDirectory, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File", formattedFile, "File"));
1179 }
1180 }
1181 else
1182 {
1183 this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "PerfmonManifest"));
1184 }
1185 }
1186 }
1187 }
1188
1189 /// <summary>
1190 /// Finalize the SecureObjects table.
1191 /// </summary>
1192 /// <param name="tables">The collection of all tables.</param>
1193 /// <remarks>
1194 /// Nests the PermissionEx elements below their parent elements. There are no declared foreign
1195 /// keys for the parents of the SecureObjects table.
1196 /// </remarks>
1197 private void FinalizeSecureObjectsTable(TableIndexedCollection tables)
1198 {
1199 Table createFolderTable = tables["CreateFolder"];
1200 Table secureObjectsTable = tables["SecureObjects"];
1201
1202 Hashtable createFolders = new Hashtable();
1203
1204 // index the CreateFolder table because the foreign key to this table from the
1205 // LockPermissions table is only part of the primary key of this table
1206 if (null != createFolderTable)
1207 {
1208 foreach (Row row in createFolderTable.Rows)
1209 {
1210 Wix.CreateFolder createFolder = (Wix.CreateFolder)this.Core.GetIndexedElement(row);
1211 string directoryId = (string)row[0];
1212
1213 if (!createFolders.Contains(directoryId))
1214 {
1215 createFolders.Add(directoryId, new ArrayList());
1216 }
1217 ((ArrayList)createFolders[directoryId]).Add(createFolder);
1218 }
1219 }
1220
1221 if (null != secureObjectsTable)
1222 {
1223 foreach (Row row in secureObjectsTable.Rows)
1224 {
1225 string id = (string)row[0];
1226 string table = (string)row[1];
1227
1228 Util.PermissionEx permissionEx = (Util.PermissionEx)this.Core.GetIndexedElement(row);
1229
1230 if ("CreateFolder" == table)
1231 {
1232 ArrayList createFolderElements = (ArrayList)createFolders[id];
1233
1234 if (null != createFolderElements)
1235 {
1236 foreach (Wix.CreateFolder createFolder in createFolderElements)
1237 {
1238 createFolder.AddChild(permissionEx);
1239 }
1240 }
1241 else
1242 {
1243 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
1244 }
1245 }
1246 else
1247 {
1248 Wix.IParentElement parentElement = (Wix.IParentElement)this.Core.GetIndexedElement(table, id);
1249
1250 if (null != parentElement)
1251 {
1252 parentElement.AddChild(permissionEx);
1253 }
1254 else
1255 {
1256 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
1257 }
1258 }
1259 }
1260 }
1261 }
1262
1263 /// <summary>
1264 /// Finalize the ServiceConfig table.
1265 /// </summary>
1266 /// <param name="tables">The collection of all tables.</param>
1267 /// <remarks>
1268 /// Since there is no foreign key from the ServiceName column to the
1269 /// ServiceInstall table, this relationship must be handled late.
1270 /// </remarks>
1271 private void FinalizeServiceConfigTable(TableIndexedCollection tables)
1272 {
1273 Table serviceConfigTable = tables["ServiceConfig"];
1274 Table serviceInstallTable = tables["ServiceInstall"];
1275
1276 Hashtable serviceInstalls = new Hashtable();
1277
1278 // index the ServiceInstall table because the foreign key used by the ServiceConfig
1279 // table is actually the ServiceInstall.Name, not the ServiceInstall.ServiceInstall
1280 // this is unfortunate because the service Name is not guaranteed to be unique, so
1281 // decompiler must assume there could be multiple matches and add the ServiceConfig to each
1282 // TODO: the Component column information should be taken into acount to accurately identify
1283 // the correct column to use
1284 if (null != serviceInstallTable)
1285 {
1286 foreach (Row row in serviceInstallTable.Rows)
1287 {
1288 string name = (string)row[1];
1289 Wix.ServiceInstall serviceInstall = (Wix.ServiceInstall)this.Core.GetIndexedElement(row);
1290
1291 if (!serviceInstalls.Contains(name))
1292 {
1293 serviceInstalls.Add(name, new ArrayList());
1294 }
1295
1296 ((ArrayList)serviceInstalls[name]).Add(serviceInstall);
1297 }
1298 }
1299
1300 if (null != serviceConfigTable)
1301 {
1302 foreach (Row row in serviceConfigTable.Rows)
1303 {
1304 Util.ServiceConfig serviceConfig = (Util.ServiceConfig)this.Core.GetIndexedElement(row);
1305
1306 if (0 == (int)row[2])
1307 {
1308 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
1309
1310 if (null != component)
1311 {
1312 component.AddChild(serviceConfig);
1313 }
1314 else
1315 {
1316 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
1317 }
1318 }
1319 else
1320 {
1321 ArrayList serviceInstallElements = (ArrayList)serviceInstalls[row[0]];
1322
1323 if (null != serviceInstallElements)
1324 {
1325 foreach (Wix.ServiceInstall serviceInstall in serviceInstallElements)
1326 {
1327 serviceInstall.AddChild(serviceConfig);
1328 }
1329 }
1330 else
1331 {
1332 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ServiceName", (string)row[0], "ServiceInstall"));
1333 }
1334 }
1335 }
1336 }
1337 }
1338
1339 /// <summary>
1340 /// Finalize the XmlConfig table.
1341 /// </summary>
1342 /// <param name="tables">Collection of all tables.</param>
1343 private void FinalizeXmlConfigTable(TableIndexedCollection tables)
1344 {
1345 Table xmlConfigTable = tables["XmlConfig"];
1346
1347 if (null != xmlConfigTable)
1348 {
1349 foreach (Row row in xmlConfigTable.Rows)
1350 {
1351 Util.XmlConfig xmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement(row);
1352
1353 if (null == row[6] || 0 == (int)row[6])
1354 {
1355 Util.XmlConfig parentXmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement("XmlConfig", (string)row[2]);
1356
1357 if (null != parentXmlConfig)
1358 {
1359 parentXmlConfig.AddChild(xmlConfig);
1360 }
1361 else
1362 {
1363 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ElementPath", (string)row[2], "XmlConfig"));
1364 }
1365 }
1366 else
1367 {
1368 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[7]);
1369
1370 if (null != component)
1371 {
1372 component.AddChild(xmlConfig);
1373 }
1374 else
1375 {
1376 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[7], "Component"));
1377 }
1378 }
1379 }
1380 }
1381 }
1382
1383
1384 /// <summary>
1385 /// Finalize the XmlFile table.
1386 /// </summary>
1387 /// <param name="tables">The collection of all tables.</param>
1388 /// <remarks>
1389 /// Some of the XmlFile table rows are compiler generated from util:EventManifest node
1390 /// These rows should not be appended to component.
1391 /// </remarks>
1392 private void FinalizeXmlFileTable(TableIndexedCollection tables)
1393 {
1394 Table xmlFileTable = tables["XmlFile"];
1395 Table eventManifestTable = tables["EventManifest"];
1396
1397 if (null != xmlFileTable)
1398 {
1399 foreach (Row row in xmlFileTable.Rows)
1400 {
1401 bool bManifestGenerated = false;
1402 string xmlFileConfigId = (string)row[0];
1403 if (null != eventManifestTable)
1404 {
1405 foreach (Row emrow in eventManifestTable.Rows)
1406 {
1407 string formattedFile = (string)emrow[1];
1408 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
1409 && formattedFile.EndsWith("]", StringComparison.Ordinal))
1410 {
1411 string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1412 if (String.Equals(String.Concat("Config_", fileId, "ResourceFile"), xmlFileConfigId))
1413 {
1414 Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow);
1415 if (null != eventManifest)
1416 {
1417 eventManifest.ResourceFile = (string)row[4];
1418 }
1419 bManifestGenerated = true;
1420 }
1421
1422 else if (String.Equals(String.Concat("Config_", fileId, "MessageFile"), xmlFileConfigId))
1423 {
1424 Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow);
1425 if (null != eventManifest)
1426 {
1427 eventManifest.MessageFile = (string)row[4];
1428 }
1429 bManifestGenerated = true;
1430 }
1431 }
1432 }
1433 }
1434
1435 if (true == bManifestGenerated)
1436 continue;
1437
1438 Util.XmlFile xmlFile = new Util.XmlFile();
1439
1440 xmlFile.Id = (string)row[0];
1441 xmlFile.File = (string)row[1];
1442 xmlFile.ElementPath = (string)row[2];
1443
1444 if (null != row[3])
1445 {
1446 xmlFile.Name = (string)row[3];
1447 }
1448
1449 if (null != row[4])
1450 {
1451 xmlFile.Value = (string)row[4];
1452 }
1453
1454 int flags = (int)row[5];
1455 if (0x1 == (flags & 0x1) && 0x2 == (flags & 0x2))
1456 {
1457 this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, xmlFileTable.Name, row.Fields[5].Column.Name, row[5]));
1458 }
1459 else if (0x1 == (flags & 0x1))
1460 {
1461 xmlFile.Action = Util.XmlFile.ActionType.createElement;
1462 }
1463 else if (0x2 == (flags & 0x2))
1464 {
1465 xmlFile.Action = Util.XmlFile.ActionType.deleteValue;
1466 }
1467 else
1468 {
1469 xmlFile.Action = Util.XmlFile.ActionType.setValue;
1470 }
1471
1472 if (0x100 == (flags & 0x100))
1473 {
1474 xmlFile.SelectionLanguage = Util.XmlFile.SelectionLanguageType.XPath;
1475 }
1476
1477 if (0x00001000 == (flags & 0x00001000))
1478 {
1479 xmlFile.PreserveModifiedDate = Util.YesNoType.yes;
1480 }
1481
1482 if (0x00010000 == (flags & 0x00010000))
1483 {
1484 xmlFile.Permanent = Util.YesNoType.yes;
1485 }
1486
1487 if (null != row[7])
1488 {
1489 xmlFile.Sequence = (int)row[7];
1490 }
1491
1492 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[6]);
1493
1494 if (null != component)
1495 {
1496 component.AddChild(xmlFile);
1497 }
1498 else
1499 {
1500 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlFileTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[6], "Component"));
1501 }
1502 }
1503 }
1504 }
1505
1506 /// <summary>
1507 /// Finalize the eventManifest table.
1508 /// This function must be called after FinalizeXmlFileTable
1509 /// </summary>
1510 /// <param name="tables">The collection of all tables.</param>
1511 private void FinalizeEventManifestTable(TableIndexedCollection tables)
1512 {
1513 Table eventManifestTable = tables["EventManifest"];
1514
1515 if (null != eventManifestTable)
1516 {
1517 foreach (Row row in eventManifestTable.Rows)
1518 {
1519 string formattedFile = (string)row[1];
1520 Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(row);
1521
1522 // try to "de-format" the File column's value to determine the proper parent File element
1523 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
1524 && formattedFile.EndsWith("]", StringComparison.Ordinal))
1525 {
1526 string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1527
1528 Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId);
1529 if (null != file)
1530 {
1531 file.AddChild(eventManifest);
1532 }
1533 }
1534 else
1535 {
1536 this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "EventManifest"));
1537 }
1538 }
1539 }
1540 }
1541 }
1542#endif
1543}
diff --git a/src/ext/Util/wixext/UtilErrors.cs b/src/ext/Util/wixext/UtilErrors.cs
new file mode 100644
index 00000000..b9ce1688
--- /dev/null
+++ b/src/ext/Util/wixext/UtilErrors.cs
@@ -0,0 +1,49 @@
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.Util
4{
5 using System;
6 using System.Resources;
7 using WixToolset.Data;
8
9 public static class UtilErrors
10 {
11 public static Message IllegalAttributeWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName)
12 {
13 return Message(sourceLineNumbers, Ids.IllegalAttributeWithoutComponent, "The {0}/@{1} attribute cannot be specified unless the element has a Component as an ancestor. A {0} that does not have a Component ancestor is not installed.", elementName, attributeName);
14 }
15
16 public static Message IllegalElementWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName)
17 {
18 return Message(sourceLineNumbers, Ids.IllegalElementWithoutComponent, "The {0} element cannot be specified unless the element has a Component as an ancestor. A {0} that does not have a Component ancestor is not installed.", elementName);
19 }
20
21 public static Message IllegalFileValueInPerfmonOrManifest(string file, string table)
22 {
23 return Message(null, Ids.IllegalFileValueInPerfmonOrManifest, "The value '{0}' in the File column, {1} table is invalid. It should be in the form of '[#file]' or '[!file]'.", file, table);
24 }
25
26 public static Message InvalidRegistryObject(SourceLineNumber sourceLineNumbers, string registryElementName)
27 {
28 return Message(sourceLineNumbers, Ids.InvalidRegistryObject, "The {0} element has no id and cannot have its permissions set. If you want to set permissions on a 'placeholder' registry key, force its creation by setting the ForceCreateOnInstall attribute to yes.", registryElementName);
29 }
30
31 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
32 {
33 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
34 }
35
36 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args)
37 {
38 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args);
39 }
40
41 public enum Ids
42 {
43 IllegalAttributeWithoutComponent = 5050,
44 IllegalElementWithoutComponent = 5051,
45 IllegalFileValueInPerfmonOrManifest = 5054,
46 InvalidRegistryObject = 5063,
47 }
48 }
49}
diff --git a/src/ext/Util/wixext/UtilExtensionData.cs b/src/ext/Util/wixext/UtilExtensionData.cs
new file mode 100644
index 00000000..d3ca3358
--- /dev/null
+++ b/src/ext/Util/wixext/UtilExtensionData.cs
@@ -0,0 +1,23 @@
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.Util
4{
5 using WixToolset.Data;
6 using WixToolset.Extensibility;
7
8 public sealed class UtilExtensionData : BaseExtensionData
9 {
10 public override string DefaultCulture => "en-US";
11
12 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
13 {
14 symbolDefinition = UtilSymbolDefinitions.ByName(name);
15 return symbolDefinition != null;
16 }
17
18 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
19 {
20 return Intermediate.Load(typeof(UtilExtensionData).Assembly, "WixToolset.Util.util.wixlib", symbolDefinitions);
21 }
22 }
23}
diff --git a/src/ext/Util/wixext/UtilExtensionFactory.cs b/src/ext/Util/wixext/UtilExtensionFactory.cs
new file mode 100644
index 00000000..08352813
--- /dev/null
+++ b/src/ext/Util/wixext/UtilExtensionFactory.cs
@@ -0,0 +1,18 @@
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.Util
4{
5 using System;
6 using System.Collections.Generic;
7 using WixToolset.Extensibility;
8
9 public class UtilExtensionFactory : BaseExtensionFactory
10 {
11 protected override IReadOnlyCollection<Type> ExtensionTypes => new[]
12 {
13 typeof(UtilCompiler),
14 typeof(UtilExtensionData),
15 typeof(UtilWindowsInstallerBackendBinderExtension),
16 };
17 }
18}
diff --git a/src/ext/Util/wixext/UtilTableDefinitions.cs b/src/ext/Util/wixext/UtilTableDefinitions.cs
new file mode 100644
index 00000000..12f423cc
--- /dev/null
+++ b/src/ext/Util/wixext/UtilTableDefinitions.cs
@@ -0,0 +1,319 @@
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.Util
4{
5 using WixToolset.Data.WindowsInstaller;
6
7 public static class UtilTableDefinitions
8 {
9 public static readonly TableDefinition Wix4CloseApplication = new TableDefinition(
10 "Wix4CloseApplication",
11 UtilSymbolDefinitions.WixCloseApplication,
12 new[]
13 {
14 new ColumnDefinition("Wix4CloseApplication", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in table.", modularizeType: ColumnModularizeType.Column),
15 new ColumnDefinition("Target", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Name of executable to ensure is closed.", modularizeType: ColumnModularizeType.Property),
16 new ColumnDefinition("Description", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description string displayed to user when executable is in use.", modularizeType: ColumnModularizeType.Property, forceLocalizable: true),
17 new ColumnDefinition("Condition", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Condition, description: "Optional expression which skips the closing.", modularizeType: ColumnModularizeType.Condition, forceLocalizable: true),
18 new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "A 32-bit word that specifies the attribute flags to be applied."),
19 new ColumnDefinition("Sequence", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 1, maxValue: 2147483647, description: "Sequence to order the closings by."),
20 new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, description: "Optional property that is set to the number of running instances of the app.", modularizeType: ColumnModularizeType.Property, forceLocalizable: true),
21 new ColumnDefinition("TerminateExitCode", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "Exit code to return from a terminated application."),
22 new ColumnDefinition("Timeout", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 1, maxValue: 2147483647, description: "Timeout in milliseconds before scheduling restart or terminating application."),
23 },
24 symbolIdIsPrimaryKey: true
25 );
26
27 public static readonly TableDefinition Wix4RemoveFolderEx = new TableDefinition(
28 "Wix4RemoveFolderEx",
29 UtilSymbolDefinitions.WixRemoveFolderEx,
30 new[]
31 {
32 new ColumnDefinition("Wix4RemoveFolderEx", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Identifier for the WixRemoveFolderEx row in the package.", modularizeType: ColumnModularizeType.Column),
33 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column),
34 new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, description: "Name of Property that contains the root of the directory tree to remove.", modularizeType: ColumnModularizeType.Column),
35 new ColumnDefinition("InstallMode", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 3, description: "1 == Remove only when the associated component is being installed (msiInstallStateLocal or msiInstallStateSource), 2 == Remove only when the associated component is being removed (msiInstallStateAbsent), 3 = Remove in either of the above cases."),
36 new ColumnDefinition("Condition", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Condition, description: "Optional expression which skips the removing of folders.", modularizeType: ColumnModularizeType.Condition, forceLocalizable: true),
37 },
38 symbolIdIsPrimaryKey: true
39 );
40
41 public static readonly TableDefinition Wix4RemoveRegistryKeyEx = new TableDefinition(
42 "Wix4RemoveRegistryKeyEx",
43 UtilSymbolDefinitions.WixRemoveRegistryKeyEx,
44 new[]
45 {
46 new ColumnDefinition("Wix4RemoveRegistryKeyEx", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Identifier for the Wix4RemoveRegistryKeyEx row in the package.", modularizeType: ColumnModularizeType.Column),
47 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column),
48 new ColumnDefinition("Root", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: -1, maxValue: 3, description: "The predefined root key for the registry value, one of rrkEnum."),
49 new ColumnDefinition("Key", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.RegPath, description: "The key for the registry value.", modularizeType: ColumnModularizeType.Property),
50 new ColumnDefinition("InstallMode", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 3, description: "1 == Remove only when the associated component is being installed (msiInstallStateLocal or msiInstallStateSource), 2 == Remove only when the associated component is being removed (msiInstallStateAbsent), 3 = Remove in either of the above cases."),
51 new ColumnDefinition("Condition", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Condition, description: "Optional expression to control whether the registry key is removed.", modularizeType: ColumnModularizeType.Condition, forceLocalizable: true),
52 },
53 symbolIdIsPrimaryKey: true
54 );
55
56 public static readonly TableDefinition Wix4RestartResource = new TableDefinition(
57 "Wix4RestartResource",
58 UtilSymbolDefinitions.WixRestartResource,
59 new[]
60 {
61 new ColumnDefinition("Wix4RestartResource", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized identifier.", modularizeType: ColumnModularizeType.Column),
62 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state.", modularizeType: ColumnModularizeType.Column),
63 new ColumnDefinition("Resource", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The resource to be registered with the Restart Manager.", modularizeType: ColumnModularizeType.Property),
64 new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 2147483647, description: "A 32-bit word that specifies the type of resource and flags used for processing."),
65 },
66 symbolIdIsPrimaryKey: true
67 );
68
69 public static readonly TableDefinition Wix4FileShare = new TableDefinition(
70 "Wix4FileShare",
71 UtilSymbolDefinitions.FileShare,
72 new[]
73 {
74 new ColumnDefinition("Wix4FileShare", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized identifier", modularizeType: ColumnModularizeType.Column),
75 new ColumnDefinition("ShareName", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The actual share name used"),
76 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column),
77 new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Description string displayed for the file share"),
78 new ColumnDefinition("Directory_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Directory", keyColumn: 1, description: "Foreign key referencing directory that the share is created on", modularizeType: ColumnModularizeType.Column),
79 },
80 symbolIdIsPrimaryKey: true
81 );
82
83 public static readonly TableDefinition Wix4FileSharePermissions = new TableDefinition(
84 "Wix4FileSharePermissions",
85 UtilSymbolDefinitions.FileSharePermissions,
86 new[]
87 {
88 new ColumnDefinition("Wix4FileShare_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "FileShare", keyColumn: 1, description: "FileShare that these premissions are to be applied to.", modularizeType: ColumnModularizeType.Column),
89 new ColumnDefinition("Wix4User_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4User", description: "User that these premissions are to apply to.", modularizeType: ColumnModularizeType.Column),
90 new ColumnDefinition("Permissions", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Permissions int, as in EXPLICIT_ACCESS.grfAccessPermissions in MSDN"),
91 },
92 symbolIdIsPrimaryKey: false
93 );
94
95 public static readonly TableDefinition Wix4Group = new TableDefinition(
96 "Wix4Group",
97 UtilSymbolDefinitions.Group,
98 new[]
99 {
100 new ColumnDefinition("Wix4Group", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
101 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Text, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column),
102 new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Group name", modularizeType: ColumnModularizeType.Property),
103 new ColumnDefinition("Domain", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Group domain", modularizeType: ColumnModularizeType.Property),
104 },
105 symbolIdIsPrimaryKey: true
106 );
107
108 public static readonly TableDefinition Wix4InternetShortcut = new TableDefinition(
109 "Wix4InternetShortcut",
110 UtilSymbolDefinitions.WixInternetShortcut,
111 new[]
112 {
113 new ColumnDefinition("Wix4InternetShortcut", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in table.", modularizeType: ColumnModularizeType.Column),
114 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column),
115 new ColumnDefinition("Directory_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Directory", keyColumn: 1, description: "Foreign key referencing directory that the shortcut is created in", modularizeType: ColumnModularizeType.Column),
116 new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Name used for shortcut.", modularizeType: ColumnModularizeType.Property),
117 new ColumnDefinition("Target", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Text, description: "URL target."),
118 new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Attribute flags that control how the shortcut is created."),
119 new ColumnDefinition("IconFile", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Icon file for shortcut", modularizeType: ColumnModularizeType.Property),
120 new ColumnDefinition("IconIndex", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Index of the icon being referenced."),
121 },
122 symbolIdIsPrimaryKey: true
123 );
124
125 public static readonly TableDefinition Wix4PerformanceCategory = new TableDefinition(
126 "Wix4PerformanceCategory",
127 UtilSymbolDefinitions.PerformanceCategory,
128 new[]
129 {
130 new ColumnDefinition("Wix4PerformanceCategory", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in table.", modularizeType: ColumnModularizeType.Column),
131 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column),
132 new ColumnDefinition("Name", ColumnType.String, 80, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Name of the performance counter category."),
133 new ColumnDefinition("IniData", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Data that goes into the performance counter .ini file."),
134 new ColumnDefinition("ConstantData", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Data that goes into the performance counter .h file."),
135 },
136 symbolIdIsPrimaryKey: true
137 );
138
139 public static readonly TableDefinition Wix4Perfmon = new TableDefinition(
140 "Wix4Perfmon",
141 UtilSymbolDefinitions.Perfmon,
142 new[]
143 {
144 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column),
145 new ColumnDefinition("File", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Name of .INI file", modularizeType: ColumnModularizeType.Property),
146 new ColumnDefinition("Name", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Text, description: "Service name in registry"),
147 },
148 symbolIdIsPrimaryKey: false
149 );
150
151 public static readonly TableDefinition Wix4PerfmonManifest = new TableDefinition(
152 "Wix4PerfmonManifest",
153 UtilSymbolDefinitions.PerfmonManifest,
154 new[]
155 {
156 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column),
157 new ColumnDefinition("File", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Name of perfmon manifest file", modularizeType: ColumnModularizeType.Property),
158 new ColumnDefinition("ResourceFileDirectory", ColumnType.String, 255, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "The path of the Resource File Directory"),
159 },
160 symbolIdIsPrimaryKey: false
161 );
162
163 public static readonly TableDefinition Wix4EventManifest = new TableDefinition(
164 "Wix4EventManifest",
165 UtilSymbolDefinitions.EventManifest,
166 new[]
167 {
168 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Component used to determine install state", modularizeType: ColumnModularizeType.Column),
169 new ColumnDefinition("File", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Name of event manifest file", modularizeType: ColumnModularizeType.Property),
170 },
171 symbolIdIsPrimaryKey: false
172 );
173
174 public static readonly TableDefinition Wix4SecureObject = new TableDefinition(
175 "Wix4SecureObject",
176 UtilSymbolDefinitions.SecureObjects,
177 new[]
178 {
179 new ColumnDefinition("Wix4SecureObject", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token in Table", modularizeType: ColumnModularizeType.Column),
180 new ColumnDefinition("Table", ColumnType.String, 32, primaryKey: true, nullable: false, ColumnCategory.Text, description: "Table SecureObject should be securing"),
181 new ColumnDefinition("Domain", ColumnType.String, 255, primaryKey: true, nullable: true, ColumnCategory.Text, description: "Domain half of user account to secure", modularizeType: ColumnModularizeType.Property),
182 new ColumnDefinition("User", ColumnType.String, 255, primaryKey: true, nullable: false, ColumnCategory.Text, description: "User name half of user account to secure", modularizeType: ColumnModularizeType.Property),
183 new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 0, maxValue: 2147483647, description: "A 32-bit word that specifies the attribute flags to be applied."),
184 new ColumnDefinition("Permission", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: -2147483647, maxValue: 2147483647, description: "Permissions to grant to User"),
185 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column),
186 },
187 symbolIdIsPrimaryKey: false
188 );
189
190 public static readonly TableDefinition Wix4ServiceConfig = new TableDefinition(
191 "Wix4ServiceConfig",
192 UtilSymbolDefinitions.ServiceConfig,
193 new[]
194 {
195 new ColumnDefinition("ServiceName", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Formatted, description: "Primary key, non-localized token"),
196 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state ", modularizeType: ColumnModularizeType.Column),
197 new ColumnDefinition("NewService", ColumnType.Number, 1, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 1, description: "Whether the affected service is being installed or already exists."),
198 new ColumnDefinition("FirstFailureActionType", ColumnType.String, 32, primaryKey: false, nullable: false, ColumnCategory.Text, description: "First failure action type for configured service to take."),
199 new ColumnDefinition("SecondFailureActionType", ColumnType.String, 32, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Second failure action type for configured service to take."),
200 new ColumnDefinition("ThirdFailureActionType", ColumnType.String, 32, primaryKey: false, nullable: false, ColumnCategory.Text, description: "Third failure action type for configured service to take."),
201 new ColumnDefinition("ResetPeriodInDays", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 0, description: "Period after which to reset the failure count for the service."),
202 new ColumnDefinition("RestartServiceDelayInSeconds", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 0, description: "Period after which to restart the service after a given failure."),
203 new ColumnDefinition("ProgramCommandLine", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Command line for program to run if failure action is RUN_COMMAND."),
204 new ColumnDefinition("RebootMessage", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Text, description: "Message to show to users when rebooting if failure action is REBOOT."),
205 },
206 symbolIdIsPrimaryKey: false
207 );
208
209 public static readonly TableDefinition Wix4TouchFile = new TableDefinition(
210 "Wix4TouchFile",
211 UtilSymbolDefinitions.WixTouchFile,
212 new[]
213 {
214 new ColumnDefinition("Wix4TouchFile", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Identifier for the Wix4TouchFile row in the package.", modularizeType: ColumnModularizeType.Column),
215 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column),
216 new ColumnDefinition("Path", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Formatted column that resolves to the path to touch.", modularizeType: ColumnModularizeType.Property),
217 new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 63, description: "1 == Touch only when the associated component is being installed, 2 == Touch only when the associated component is being repaired , 4 == Touch only when the associated component is being removed, 16 = path is in 64-bit location, 32 = touching the file is vital."),
218 },
219 symbolIdIsPrimaryKey: true
220 );
221
222 public static readonly TableDefinition Wix4User = new TableDefinition(
223 "Wix4User",
224 UtilSymbolDefinitions.User,
225 new[]
226 {
227 new ColumnDefinition("Wix4User", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
228 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Text, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column),
229 new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "User name", modularizeType: ColumnModularizeType.Property),
230 new ColumnDefinition("Domain", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "User domain", modularizeType: ColumnModularizeType.Property),
231 new ColumnDefinition("Password", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "User password", modularizeType: ColumnModularizeType.Property),
232 new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 0, maxValue: 65535, description: "Attributes describing how to create the user"),
233 },
234 symbolIdIsPrimaryKey: true
235 );
236
237 public static readonly TableDefinition Wix4UserGroup = new TableDefinition(
238 "Wix4UserGroup",
239 UtilSymbolDefinitions.UserGroup,
240 new[]
241 {
242 new ColumnDefinition("Wix4User_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4User", keyColumn: 1, description: "User to be joined to a Group.", modularizeType: ColumnModularizeType.Column),
243 new ColumnDefinition("Wix4Group_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4Group", keyColumn: 1, description: "Group to join User to.", modularizeType: ColumnModularizeType.Column),
244 },
245 symbolIdIsPrimaryKey: false
246 );
247
248 public static readonly TableDefinition Wix4XmlFile = new TableDefinition(
249 "Wix4XmlFile",
250 UtilSymbolDefinitions.XmlFile,
251 new[]
252 {
253 new ColumnDefinition("Wix4XmlFile", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token.", modularizeType: ColumnModularizeType.Column),
254 new ColumnDefinition("File", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The .XML file in which to write the information", modularizeType: ColumnModularizeType.Property),
255 new ColumnDefinition("ElementPath", ColumnType.Localized, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The .XML file element to modify.", modularizeType: ColumnModularizeType.Property),
256 new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The .XML file node to set/add in the element.", modularizeType: ColumnModularizeType.Property),
257 new ColumnDefinition("Value", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The value to be written.", modularizeType: ColumnModularizeType.Property),
258 new ColumnDefinition("Flags", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 70143, description: "Flags"),
259 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the installing of the .XML value.", modularizeType: ColumnModularizeType.Column),
260 new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to execute the XML modifications."),
261 },
262 symbolIdIsPrimaryKey: true
263 );
264
265 public static readonly TableDefinition Wix4XmlConfig = new TableDefinition(
266 "Wix4XmlConfig",
267 UtilSymbolDefinitions.XmlConfig,
268 new[]
269 {
270 new ColumnDefinition("Wix4XmlConfig", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token.", modularizeType: ColumnModularizeType.Column),
271 new ColumnDefinition("File", ColumnType.Localized, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "The .XML file in which to write the information", modularizeType: ColumnModularizeType.Property),
272 new ColumnDefinition("ElementId", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Wix4XmlConfig", keyColumn: 1, description: "A foreign key reference to another Wix4XmlConfig row if no attributes are set and the row referenced is a create element row.", modularizeType: ColumnModularizeType.Column),
273 new ColumnDefinition("ElementPath", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The XPATH query for an element to modify or add children to. Must be null if ElementId is provided", modularizeType: ColumnModularizeType.Property),
274 new ColumnDefinition("VerifyPath", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The XPATH query run from ElementPath to verify whether a repair is necessary. Also used to uninstall.", modularizeType: ColumnModularizeType.Property),
275 new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The .XML file node to set/add in the element.", modularizeType: ColumnModularizeType.Property),
276 new ColumnDefinition("Value", ColumnType.Localized, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The value to be written.", modularizeType: ColumnModularizeType.Property),
277 new ColumnDefinition("Flags", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 0, maxValue: 65536, description: "Element=1,Value=2,Document=4,Create=16,Delete=32,Install=256,Uninstall=512"),
278 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the installing of the .XML value.", modularizeType: ColumnModularizeType.Column),
279 new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to execute the XML modifications."),
280 },
281 symbolIdIsPrimaryKey: true
282 );
283
284 public static readonly TableDefinition Wix4FormatFile = new TableDefinition(
285 "Wix4FormatFile",
286 UtilSymbolDefinitions.WixFormatFiles,
287 new[]
288 {
289 new ColumnDefinition("Binary_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Binary", keyColumn: 1, description: "Binary data to be formatted.", modularizeType: ColumnModularizeType.Column),
290 new ColumnDefinition("File_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "File", keyColumn: 1, description: "File whose component controls the custom action and where the formatted data is written.", modularizeType: ColumnModularizeType.Column),
291 },
292 symbolIdIsPrimaryKey: false
293 );
294
295 public static readonly TableDefinition[] All = new[]
296 {
297 Wix4CloseApplication,
298 Wix4RemoveFolderEx,
299 Wix4RemoveRegistryKeyEx,
300 Wix4RestartResource,
301 Wix4FileShare,
302 Wix4FileSharePermissions,
303 Wix4Group,
304 Wix4InternetShortcut,
305 Wix4PerformanceCategory,
306 Wix4Perfmon,
307 Wix4PerfmonManifest,
308 Wix4EventManifest,
309 Wix4SecureObject,
310 Wix4ServiceConfig,
311 Wix4TouchFile,
312 Wix4User,
313 Wix4UserGroup,
314 Wix4XmlFile,
315 Wix4XmlConfig,
316 Wix4FormatFile,
317 };
318 }
319}
diff --git a/src/ext/Util/wixext/UtilWarnings.cs b/src/ext/Util/wixext/UtilWarnings.cs
new file mode 100644
index 00000000..b65abe45
--- /dev/null
+++ b/src/ext/Util/wixext/UtilWarnings.cs
@@ -0,0 +1,37 @@
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.Util
4{
5 using System;
6 using System.Resources;
7 using WixToolset.Data;
8
9 public static class UtilWarnings
10 {
11 public static Message DeprecatedPerfCounterElement(SourceLineNumber sourceLineNumbers)
12 {
13 return Message(sourceLineNumbers, Ids.DeprecatedPerfCounterElement, "The PerfCounter element has been deprecated. Please use the PerformanceCounter element instead.");
14 }
15
16 public static Message RequiredAttributeForWindowsXP(SourceLineNumber sourceLineNumbers, string elementName, string attributeName)
17 {
18 return Message(sourceLineNumbers, Ids.RequiredAttributeForWindowsXP, "The {0}/@{1} attribute must be specified to successfully install on Windows XP. You can ignore this warning if this installation does not install on Windows XP.", elementName, attributeName);
19 }
20
21 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
22 {
23 return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args);
24 }
25
26 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args)
27 {
28 return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, resourceManager, resourceName, args);
29 }
30
31 public enum Ids
32 {
33 DeprecatedPerfCounterElement = 5153,
34 RequiredAttributeForWindowsXP = 5154,
35 }
36 }
37}
diff --git a/src/ext/Util/wixext/UtilWindowsInstallerBackendExtension.cs b/src/ext/Util/wixext/UtilWindowsInstallerBackendExtension.cs
new file mode 100644
index 00000000..bca7c700
--- /dev/null
+++ b/src/ext/Util/wixext/UtilWindowsInstallerBackendExtension.cs
@@ -0,0 +1,13 @@
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.Util
4{
5 using System.Collections.Generic;
6 using WixToolset.Data.WindowsInstaller;
7 using WixToolset.Extensibility;
8
9 public class UtilWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension
10 {
11 public override IReadOnlyCollection<TableDefinition> TableDefinitions => UtilTableDefinitions.All;
12 }
13}
diff --git a/src/ext/Util/wixext/WixToolset.Util.wixext.csproj b/src/ext/Util/wixext/WixToolset.Util.wixext.csproj
new file mode 100644
index 00000000..10fc569e
--- /dev/null
+++ b/src/ext/Util/wixext/WixToolset.Util.wixext.csproj
@@ -0,0 +1,31 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5 <PropertyGroup>
6 <TargetFramework>netstandard2.0</TargetFramework>
7 <RootNamespace>WixToolset.Util</RootNamespace>
8 <Description>WiX Toolset Utility Extension</Description>
9 <Title>WiX Toolset Util Extension</Title>
10 <DebugType>embedded</DebugType>
11 <IncludeSymbols>true</IncludeSymbols>
12 </PropertyGroup>
13
14 <ItemGroup>
15 <EmbeddedResource Include="$(OutputPath)..\util.wixlib" />
16 </ItemGroup>
17
18 <ItemGroup>
19 <ProjectReference Include="..\wixlib\util.wixproj" ReferenceOutputAssembly="false" Condition=" '$(NCrunch)'=='' " />
20 </ItemGroup>
21
22 <ItemGroup>
23 <PackageReference Include="WixToolset.Data" Version="4.0.*" />
24 <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" />
25 </ItemGroup>
26
27 <ItemGroup>
28 <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="all" />
29 <PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="All" />
30 </ItemGroup>
31</Project>
diff --git a/src/ext/Util/wixext/WixToolset.Util.wixext.nuspec b/src/ext/Util/wixext/WixToolset.Util.wixext.nuspec
new file mode 100644
index 00000000..ba3eaade
--- /dev/null
+++ b/src/ext/Util/wixext/WixToolset.Util.wixext.nuspec
@@ -0,0 +1,25 @@
1<?xml version="1.0"?>
2<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
3 <metadata minClientVersion="4.0">
4 <id>$id$</id>
5 <version>$version$</version>
6 <title>$title$</title>
7 <description>$description$</description>
8 <authors>$authors$</authors>
9 <license type="expression">MS-RL</license>
10 <requireLicenseAcceptance>false</requireLicenseAcceptance>
11 <copyright>$copyright$</copyright>
12 <projectUrl>$projectUrl$</projectUrl>
13 <repository type="$repositorytype$" url="$repositoryurl$" commit="$repositorycommit$" />
14 </metadata>
15
16 <files>
17 <file src="$projectFolder$$id$.targets" target="build" />
18
19 <file src="netstandard2.0\$id$.dll" target="tools" />
20
21 <file src="ARM64\*.pdb" target="pdbs\ARM64" />
22 <file src="x86\*.pdb" target="pdbs\x86" />
23 <file src="x64\*.pdb" target="pdbs\x64" />
24 </files>
25</package>
diff --git a/src/ext/Util/wixext/WixToolset.Util.wixext.targets b/src/ext/Util/wixext/WixToolset.Util.wixext.targets
new file mode 100644
index 00000000..64dff429
--- /dev/null
+++ b/src/ext/Util/wixext/WixToolset.Util.wixext.targets
@@ -0,0 +1,11 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
5 <PropertyGroup>
6 <WixToolsetUtilWixextPath Condition=" '$(WixToolsetUtilWixextPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\WixToolset.Util.wixext.dll</WixToolsetUtilWixextPath>
7 </PropertyGroup>
8 <ItemGroup>
9 <WixExtension Include="$(WixToolsetUtilWixextPath)" />
10 </ItemGroup>
11</Project>
diff --git a/src/ext/Util/wixext/WixToolset.Util.wixext.v3.ncrunchproject b/src/ext/Util/wixext/WixToolset.Util.wixext.v3.ncrunchproject
new file mode 100644
index 00000000..d75e7ab3
--- /dev/null
+++ b/src/ext/Util/wixext/WixToolset.Util.wixext.v3.ncrunchproject
@@ -0,0 +1,7 @@
1<ProjectConfiguration>
2 <Settings>
3 <AdditionalFilesToIncludeForProject>
4 <Value>..\..\build\Debug\util.wixlib</Value>
5 </AdditionalFilesToIncludeForProject>
6 </Settings>
7</ProjectConfiguration> \ No newline at end of file