diff options
author | Rob Mensching <rob@firegiant.com> | 2020-01-13 09:10:13 -0800 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2020-01-13 14:19:45 -0800 |
commit | 94b941ee95a294228516097c269e27dfa41593ab (patch) | |
tree | 208cb36a5a6a3e17f5d458cfaa679d6ca1a76e15 /src | |
parent | a2b1235d9c0dfba48b1badac428d89d1137da698 (diff) | |
download | wix-94b941ee95a294228516097c269e27dfa41593ab.tar.gz wix-94b941ee95a294228516097c269e27dfa41593ab.tar.bz2 wix-94b941ee95a294228516097c269e27dfa41593ab.zip |
Provide Record enumerator on View that disposes fetched Records
Diffstat (limited to 'src')
9 files changed, 389 insertions, 390 deletions
diff --git a/src/WixToolset.Core.TestPackage/WixRunnerResult.cs b/src/WixToolset.Core.TestPackage/WixRunnerResult.cs index f4870ae3..88f20158 100644 --- a/src/WixToolset.Core.TestPackage/WixRunnerResult.cs +++ b/src/WixToolset.Core.TestPackage/WixRunnerResult.cs | |||
@@ -26,7 +26,6 @@ namespace WixToolset.Core.TestPackage | |||
26 | var filename = message.SourceLineNumbers?.FileName ?? "TEST"; | 26 | var filename = message.SourceLineNumbers?.FileName ?? "TEST"; |
27 | var line = message.SourceLineNumbers?.LineNumber ?? -1; | 27 | var line = message.SourceLineNumbers?.LineNumber ?? -1; |
28 | var type = message.Level.ToString().ToLowerInvariant(); | 28 | var type = message.Level.ToString().ToLowerInvariant(); |
29 | var output = message.Level >= MessageLevel.Warning ? Console.Out : Console.Error; | ||
30 | 29 | ||
31 | if (line > 0) | 30 | if (line > 0) |
32 | { | 31 | { |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs index 4105cb8f..5412c6f9 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs | |||
@@ -89,46 +89,38 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
89 | using (View view = db.OpenExecuteView("SELECT `File`, `Directory_` FROM `File`, `Component` WHERE `Component_`=`Component`")) | 89 | using (View view = db.OpenExecuteView("SELECT `File`, `Directory_` FROM `File`, `Component` WHERE `Component_`=`Component`")) |
90 | { | 90 | { |
91 | // add each file row from the merge module into the file row collection (check for errors along the way) | 91 | // add each file row from the merge module into the file row collection (check for errors along the way) |
92 | while (true) | 92 | foreach (Record record in view.Records) |
93 | { | 93 | { |
94 | using (Record record = view.Fetch()) | 94 | // NOTE: this is very tricky - the merge module file rows are not added to the |
95 | // file table because they should not be created via idt import. Instead, these | ||
96 | // rows are created by merging in the actual modules. | ||
97 | var fileTuple = new FileTuple(wixMergeRow.SourceLineNumbers, new Identifier(AccessModifier.Private, record[1])); | ||
98 | fileTuple.Attributes = wixMergeRow.FileAttributes; | ||
99 | fileTuple.DirectoryRef = record[2]; | ||
100 | fileTuple.DiskId = wixMergeRow.DiskId; | ||
101 | fileTuple.Source = new IntermediateFieldPathValue { Path = Path.Combine(this.IntermediateFolder, wixMergeRow.Id.Id, record[1]) }; | ||
102 | |||
103 | var mergeModuleFileFacade = new FileFacade(true, fileTuple); | ||
104 | |||
105 | // If case-sensitive collision with another merge module or a user-authored file identifier. | ||
106 | if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.Id.Id, out var collidingFacade)) | ||
95 | { | 107 | { |
96 | if (null == record) | 108 | this.Messaging.Write(ErrorMessages.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, collidingFacade.File.Id.Id)); |
97 | { | ||
98 | break; | ||
99 | } | ||
100 | |||
101 | // NOTE: this is very tricky - the merge module file rows are not added to the | ||
102 | // file table because they should not be created via idt import. Instead, these | ||
103 | // rows are created by merging in the actual modules. | ||
104 | var fileTuple = new FileTuple(wixMergeRow.SourceLineNumbers, new Identifier(AccessModifier.Private, record[1])); | ||
105 | fileTuple.Attributes = wixMergeRow.FileAttributes; | ||
106 | fileTuple.DirectoryRef = record[2]; | ||
107 | fileTuple.DiskId = wixMergeRow.DiskId; | ||
108 | fileTuple.Source = new IntermediateFieldPathValue { Path = Path.Combine(this.IntermediateFolder, wixMergeRow.Id.Id, record[1]) }; | ||
109 | |||
110 | var mergeModuleFileFacade = new FileFacade(true, fileTuple); | ||
111 | |||
112 | // If case-sensitive collision with another merge module or a user-authored file identifier. | ||
113 | if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.Id.Id, out var collidingFacade)) | ||
114 | { | ||
115 | this.Messaging.Write(ErrorMessages.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, collidingFacade.File.Id.Id)); | ||
116 | } | ||
117 | else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.Id.Id, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module | ||
118 | { | ||
119 | this.Messaging.Write(ErrorMessages.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, mergeModuleFileFacade.File.Id.Id, collidingFacade.File.Id.Id)); | ||
120 | } | ||
121 | else // no collision | ||
122 | { | ||
123 | mergeModulesFileFacades.Add(mergeModuleFileFacade); | ||
124 | |||
125 | // Keep updating the indexes as new rows are added. | ||
126 | indexedFileFacades.Add(mergeModuleFileFacade.File.Id.Id, mergeModuleFileFacade); | ||
127 | uniqueModuleFileIdentifiers.Add(mergeModuleFileFacade.File.Id.Id, mergeModuleFileFacade); | ||
128 | } | ||
129 | |||
130 | containsFiles = true; | ||
131 | } | 109 | } |
110 | else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.Id.Id, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module | ||
111 | { | ||
112 | this.Messaging.Write(ErrorMessages.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, mergeModuleFileFacade.File.Id.Id, collidingFacade.File.Id.Id)); | ||
113 | } | ||
114 | else // no collision | ||
115 | { | ||
116 | mergeModulesFileFacades.Add(mergeModuleFileFacade); | ||
117 | |||
118 | // Keep updating the indexes as new rows are added. | ||
119 | indexedFileFacades.Add(mergeModuleFileFacade.File.Id.Id, mergeModuleFileFacade); | ||
120 | uniqueModuleFileIdentifiers.Add(mergeModuleFileFacade.File.Id.Id, mergeModuleFileFacade); | ||
121 | } | ||
122 | |||
123 | containsFiles = true; | ||
132 | } | 124 | } |
133 | } | 125 | } |
134 | } | 126 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs index 7ee33997..8c11555e 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs | |||
@@ -220,14 +220,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
220 | string query = String.Format(CultureInfo.InvariantCulture, "SELECT * FROM {0} WHERE `Action` = '{1}'", row[0].ToString(), (string)row[1]); | 220 | string query = String.Format(CultureInfo.InvariantCulture, "SELECT * FROM {0} WHERE `Action` = '{1}'", row[0].ToString(), (string)row[1]); |
221 | 221 | ||
222 | using (View view = db.OpenExecuteView(query)) | 222 | using (View view = db.OpenExecuteView(query)) |
223 | using (Record record = view.Fetch()) | ||
223 | { | 224 | { |
224 | using (Record record = view.Fetch()) | 225 | if (null != record) |
225 | { | 226 | { |
226 | if (null != record) | 227 | this.Messaging.Write(WarningMessages.SuppressMergedAction((string)row[1], row[0].ToString())); |
227 | { | 228 | view.Modify(ModifyView.Delete, record); |
228 | this.Messaging.Write(WarningMessages.SuppressMergedAction((string)row[1], row[0].ToString())); | ||
229 | view.Modify(ModifyView.Delete, record); | ||
230 | } | ||
231 | } | 229 | } |
232 | } | 230 | } |
233 | } | 231 | } |
@@ -244,17 +242,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
244 | 242 | ||
245 | using (View view = db.OpenExecuteView(String.Concat("SELECT `Action` FROM ", tableName))) | 243 | using (View view = db.OpenExecuteView(String.Concat("SELECT `Action` FROM ", tableName))) |
246 | { | 244 | { |
247 | while (true) | 245 | foreach (Record resultRecord in view.Records) |
248 | { | 246 | { |
249 | using (Record resultRecord = view.Fetch()) | 247 | this.Messaging.Write(WarningMessages.SuppressMergedAction(resultRecord.GetString(1), tableName)); |
250 | { | ||
251 | if (null == resultRecord) | ||
252 | { | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | this.Messaging.Write(WarningMessages.SuppressMergedAction(resultRecord.GetString(1), tableName)); | ||
257 | } | ||
258 | } | 248 | } |
259 | } | 249 | } |
260 | 250 | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs index 64fb3e4d..373ada38 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs | |||
@@ -57,25 +57,17 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
57 | 57 | ||
58 | var mediaRows = this.Section.Tuples.OfType<MediaTuple>().ToDictionary(t => t.DiskId); | 58 | var mediaRows = this.Section.Tuples.OfType<MediaTuple>().ToDictionary(t => t.DiskId); |
59 | 59 | ||
60 | using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) | 60 | using (var db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) |
61 | { | 61 | { |
62 | using (View directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) | 62 | using (var directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) |
63 | { | 63 | { |
64 | while (true) | 64 | foreach (var directoryRecord in directoryView.Records) |
65 | { | 65 | { |
66 | using (Record directoryRecord = directoryView.Fetch()) | 66 | var sourceName = Common.GetName(directoryRecord.GetString(3), true, this.LongNamesInImage); |
67 | { | ||
68 | if (null == directoryRecord) | ||
69 | { | ||
70 | break; | ||
71 | } | ||
72 | 67 | ||
73 | string sourceName = Common.GetName(directoryRecord.GetString(3), true, this.LongNamesInImage); | 68 | var resolvedDirectory = this.BackendHelper.CreateResolvedDirectory(directoryRecord.GetString(2), sourceName); |
74 | 69 | ||
75 | var resolvedDirectory = this.BackendHelper.CreateResolvedDirectory(directoryRecord.GetString(2), sourceName); | 70 | directories.Add(directoryRecord.GetString(1), resolvedDirectory); |
76 | |||
77 | directories.Add(directoryRecord.GetString(1), resolvedDirectory); | ||
78 | } | ||
79 | } | 71 | } |
80 | } | 72 | } |
81 | 73 | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs b/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs index b91eeeef..ff7472ff 100644 --- a/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs | |||
@@ -60,47 +60,39 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe | |||
60 | { | 60 | { |
61 | using (View digitalSignatureView = database.OpenExecuteView("SELECT `Table`, `SignObject`, `DigitalCertificate_`, `Hash` FROM `MsiDigitalSignature` WHERE `Table` <> 'Media'")) | 61 | using (View digitalSignatureView = database.OpenExecuteView("SELECT `Table`, `SignObject`, `DigitalCertificate_`, `Hash` FROM `MsiDigitalSignature` WHERE `Table` <> 'Media'")) |
62 | { | 62 | { |
63 | while (true) | 63 | foreach (Record digitalSignatureRecord in digitalSignatureView.Records) |
64 | { | 64 | { |
65 | using (Record digitalSignatureRecord = digitalSignatureView.Fetch()) | 65 | Row digitalSignatureRow = null; |
66 | { | 66 | digitalSignatureRow = digitalSignatureTable.CreateRow(null); |
67 | if (null == digitalSignatureRecord) | ||
68 | { | ||
69 | break; | ||
70 | } | ||
71 | 67 | ||
72 | Row digitalSignatureRow = null; | 68 | string table = digitalSignatureRecord.GetString(0); |
73 | digitalSignatureRow = digitalSignatureTable.CreateRow(null); | 69 | string signObject = digitalSignatureRecord.GetString(1); |
74 | 70 | ||
75 | string table = digitalSignatureRecord.GetString(0); | 71 | digitalSignatureRow[0] = table; |
76 | string signObject = digitalSignatureRecord.GetString(1); | 72 | digitalSignatureRow[1] = signObject; |
73 | digitalSignatureRow[2] = digitalSignatureRecord.GetString(2); | ||
77 | 74 | ||
78 | digitalSignatureRow[0] = table; | 75 | if (false == digitalSignatureRecord.IsNull(3)) |
79 | digitalSignatureRow[1] = signObject; | 76 | { |
80 | digitalSignatureRow[2] = digitalSignatureRecord.GetString(2); | 77 | // Export to a file, because the MSI API's require us to provide a file path on disk |
78 | string hashPath = Path.Combine(this.Context.IntermediateFolder, "MsiDigitalSignature"); | ||
79 | string hashFileName = string.Concat(table, ".", signObject, ".bin"); | ||
81 | 80 | ||
82 | if (false == digitalSignatureRecord.IsNull(3)) | 81 | Directory.CreateDirectory(hashPath); |
83 | { | 82 | hashPath = Path.Combine(hashPath, hashFileName); |
84 | // Export to a file, because the MSI API's require us to provide a file path on disk | ||
85 | string hashPath = Path.Combine(this.Context.IntermediateFolder, "MsiDigitalSignature"); | ||
86 | string hashFileName = string.Concat(table, ".", signObject, ".bin"); | ||
87 | 83 | ||
88 | Directory.CreateDirectory(hashPath); | 84 | using (FileStream fs = File.Create(hashPath)) |
89 | hashPath = Path.Combine(hashPath, hashFileName); | 85 | { |
86 | int bytesRead; | ||
87 | byte[] buffer = new byte[1024 * 4]; | ||
90 | 88 | ||
91 | using (FileStream fs = File.Create(hashPath)) | 89 | while (0 != (bytesRead = digitalSignatureRecord.GetStream(3, buffer, buffer.Length))) |
92 | { | 90 | { |
93 | int bytesRead; | 91 | fs.Write(buffer, 0, bytesRead); |
94 | byte[] buffer = new byte[1024 * 4]; | ||
95 | |||
96 | while (0 != (bytesRead = digitalSignatureRecord.GetStream(3, buffer, buffer.Length))) | ||
97 | { | ||
98 | fs.Write(buffer, 0, bytesRead); | ||
99 | } | ||
100 | } | 92 | } |
101 | |||
102 | digitalSignatureRow[3] = hashFileName; | ||
103 | } | 93 | } |
94 | |||
95 | digitalSignatureRow[3] = hashFileName; | ||
104 | } | 96 | } |
105 | } | 97 | } |
106 | } | 98 | } |
@@ -111,145 +103,129 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe | |||
111 | { | 103 | { |
112 | using (View digitalCertificateView = database.OpenExecuteView("SELECT * FROM `MsiDigitalCertificate`")) | 104 | using (View digitalCertificateView = database.OpenExecuteView("SELECT * FROM `MsiDigitalCertificate`")) |
113 | { | 105 | { |
114 | while (true) | 106 | foreach (Record digitalCertificateRecord in digitalCertificateView.Records) |
115 | { | 107 | { |
116 | using (Record digitalCertificateRecord = digitalCertificateView.Fetch()) | 108 | string certificateId = digitalCertificateRecord.GetString(1); // get the identifier of the certificate |
117 | { | ||
118 | if (null == digitalCertificateRecord) | ||
119 | { | ||
120 | break; | ||
121 | } | ||
122 | 109 | ||
123 | string certificateId = digitalCertificateRecord.GetString(1); // get the identifier of the certificate | 110 | // Export to a file, because the MSI API's require us to provide a file path on disk |
111 | string certPath = Path.Combine(this.Context.IntermediateFolder, "MsiDigitalCertificate"); | ||
112 | Directory.CreateDirectory(certPath); | ||
113 | certPath = Path.Combine(certPath, string.Concat(certificateId, ".cer")); | ||
124 | 114 | ||
125 | // Export to a file, because the MSI API's require us to provide a file path on disk | 115 | using (FileStream fs = File.Create(certPath)) |
126 | string certPath = Path.Combine(this.Context.IntermediateFolder, "MsiDigitalCertificate"); | 116 | { |
127 | Directory.CreateDirectory(certPath); | 117 | int bytesRead; |
128 | certPath = Path.Combine(certPath, string.Concat(certificateId, ".cer")); | 118 | byte[] buffer = new byte[1024 * 4]; |
129 | 119 | ||
130 | using (FileStream fs = File.Create(certPath)) | 120 | while (0 != (bytesRead = digitalCertificateRecord.GetStream(2, buffer, buffer.Length))) |
131 | { | 121 | { |
132 | int bytesRead; | 122 | fs.Write(buffer, 0, bytesRead); |
133 | byte[] buffer = new byte[1024 * 4]; | ||
134 | |||
135 | while (0 != (bytesRead = digitalCertificateRecord.GetStream(2, buffer, buffer.Length))) | ||
136 | { | ||
137 | fs.Write(buffer, 0, bytesRead); | ||
138 | } | ||
139 | } | 123 | } |
124 | } | ||
140 | 125 | ||
141 | // Add it to our "add to MsiDigitalCertificate" table dictionary | 126 | // Add it to our "add to MsiDigitalCertificate" table dictionary |
142 | Row digitalCertificateRow = digitalCertificateTable.CreateRow(null); | 127 | Row digitalCertificateRow = digitalCertificateTable.CreateRow(null); |
143 | digitalCertificateRow[0] = certificateId; | 128 | digitalCertificateRow[0] = certificateId; |
144 | 129 | ||
145 | // Now set the file path on disk where this binary stream will be picked up at import time | 130 | // Now set the file path on disk where this binary stream will be picked up at import time |
146 | digitalCertificateRow[1] = string.Concat(certificateId, ".cer"); | 131 | digitalCertificateRow[1] = string.Concat(certificateId, ".cer"); |
147 | 132 | ||
148 | // Load the cert to get it's thumbprint | 133 | // Load the cert to get it's thumbprint |
149 | X509Certificate cert = X509Certificate.CreateFromCertFile(certPath); | 134 | X509Certificate cert = X509Certificate.CreateFromCertFile(certPath); |
150 | X509Certificate2 cert2 = new X509Certificate2(cert); | 135 | X509Certificate2 cert2 = new X509Certificate2(cert); |
151 | 136 | ||
152 | certificates.Add(cert2.Thumbprint, certificateId); | 137 | certificates.Add(cert2.Thumbprint, certificateId); |
153 | } | ||
154 | } | 138 | } |
155 | } | 139 | } |
156 | } | 140 | } |
157 | 141 | ||
158 | using (View mediaView = database.OpenExecuteView("SELECT * FROM `Media`")) | 142 | using (View mediaView = database.OpenExecuteView("SELECT * FROM `Media`")) |
159 | { | 143 | { |
160 | while (true) | 144 | foreach (Record mediaRecord in mediaView.Records) |
161 | { | 145 | { |
162 | using (Record mediaRecord = mediaView.Fetch()) | 146 | X509Certificate2 cert2 = null; |
147 | Row digitalSignatureRow = null; | ||
148 | |||
149 | string cabName = mediaRecord.GetString(4); // get the name of the cab | ||
150 | // If there is no cabinet or it's an internal cab, skip it. | ||
151 | if (String.IsNullOrEmpty(cabName) || cabName.StartsWith("#", StringComparison.Ordinal)) | ||
163 | { | 152 | { |
164 | if (null == mediaRecord) | 153 | continue; |
165 | { | 154 | } |
166 | break; | ||
167 | } | ||
168 | 155 | ||
169 | X509Certificate2 cert2 = null; | 156 | string cabId = mediaRecord.GetString(1); // get the ID of the cab |
170 | Row digitalSignatureRow = null; | 157 | string cabPath = Path.Combine(Path.GetDirectoryName(this.Context.InputFilePath), cabName); |
171 | 158 | ||
172 | string cabName = mediaRecord.GetString(4); // get the name of the cab | 159 | // If the cabs aren't there, throw an error but continue to catch the other errors |
173 | // If there is no cabinet or it's an internal cab, skip it. | 160 | if (!File.Exists(cabPath)) |
174 | if (String.IsNullOrEmpty(cabName) || cabName.StartsWith("#", StringComparison.Ordinal)) | 161 | { |
175 | { | 162 | this.Messaging.Write(ErrorMessages.WixFileNotFound(cabPath)); |
176 | continue; | 163 | continue; |
177 | } | 164 | } |
178 | 165 | ||
179 | string cabId = mediaRecord.GetString(1); // get the ID of the cab | 166 | try |
180 | string cabPath = Path.Combine(Path.GetDirectoryName(this.Context.InputFilePath), cabName); | 167 | { |
168 | // Get the certificate from the cab | ||
169 | X509Certificate signedFileCert = X509Certificate.CreateFromSignedFile(cabPath); | ||
170 | cert2 = new X509Certificate2(signedFileCert); | ||
171 | } | ||
172 | catch (System.Security.Cryptography.CryptographicException e) | ||
173 | { | ||
174 | uint HResult = unchecked((uint)Marshal.GetHRForException(e)); | ||
181 | 175 | ||
182 | // If the cabs aren't there, throw an error but continue to catch the other errors | 176 | // If the file has no cert, continue, but flag that we found at least one so we can later give a warning |
183 | if (!File.Exists(cabPath)) | 177 | if (0x80092009 == HResult) // CRYPT_E_NO_MATCH |
184 | { | 178 | { |
185 | this.Messaging.Write(ErrorMessages.WixFileNotFound(cabPath)); | 179 | foundUnsignedExternals = true; |
186 | continue; | 180 | continue; |
187 | } | 181 | } |
188 | 182 | ||
189 | try | 183 | // todo: exactly which HRESULT corresponds to this issue? |
184 | // If it's one of these exact platforms, warn the user that it may be due to their OS. | ||
185 | if ((5 == Environment.OSVersion.Version.Major && 2 == Environment.OSVersion.Version.Minor) || // W2K3 | ||
186 | (5 == Environment.OSVersion.Version.Major && 1 == Environment.OSVersion.Version.Minor)) // XP | ||
190 | { | 187 | { |
191 | // Get the certificate from the cab | 188 | this.Messaging.Write(ErrorMessages.UnableToGetAuthenticodeCertOfFileDownlevelOS(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult))); |
192 | X509Certificate signedFileCert = X509Certificate.CreateFromSignedFile(cabPath); | ||
193 | cert2 = new X509Certificate2(signedFileCert); | ||
194 | } | 189 | } |
195 | catch (System.Security.Cryptography.CryptographicException e) | 190 | else // otherwise, generic error |
196 | { | 191 | { |
197 | uint HResult = unchecked((uint)Marshal.GetHRForException(e)); | 192 | this.Messaging.Write(ErrorMessages.UnableToGetAuthenticodeCertOfFile(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult))); |
198 | |||
199 | // If the file has no cert, continue, but flag that we found at least one so we can later give a warning | ||
200 | if (0x80092009 == HResult) // CRYPT_E_NO_MATCH | ||
201 | { | ||
202 | foundUnsignedExternals = true; | ||
203 | continue; | ||
204 | } | ||
205 | |||
206 | // todo: exactly which HRESULT corresponds to this issue? | ||
207 | // If it's one of these exact platforms, warn the user that it may be due to their OS. | ||
208 | if ((5 == Environment.OSVersion.Version.Major && 2 == Environment.OSVersion.Version.Minor) || // W2K3 | ||
209 | (5 == Environment.OSVersion.Version.Major && 1 == Environment.OSVersion.Version.Minor)) // XP | ||
210 | { | ||
211 | this.Messaging.Write(ErrorMessages.UnableToGetAuthenticodeCertOfFileDownlevelOS(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult))); | ||
212 | } | ||
213 | else // otherwise, generic error | ||
214 | { | ||
215 | this.Messaging.Write(ErrorMessages.UnableToGetAuthenticodeCertOfFile(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult))); | ||
216 | } | ||
217 | } | 193 | } |
194 | } | ||
218 | 195 | ||
219 | // If we haven't added this cert to the MsiDigitalCertificate table, set it up to be added | 196 | // If we haven't added this cert to the MsiDigitalCertificate table, set it up to be added |
220 | if (!certificates.ContainsKey(cert2.Thumbprint)) | 197 | if (!certificates.ContainsKey(cert2.Thumbprint)) |
221 | { | 198 | { |
222 | // generate a stable identifier | 199 | // generate a stable identifier |
223 | string certificateGeneratedId = Common.GenerateIdentifier("cer", cert2.Thumbprint); | 200 | string certificateGeneratedId = Common.GenerateIdentifier("cer", cert2.Thumbprint); |
224 | |||
225 | // Add it to our "add to MsiDigitalCertificate" table dictionary | ||
226 | Row digitalCertificateRow = digitalCertificateTable.CreateRow(null); | ||
227 | digitalCertificateRow[0] = certificateGeneratedId; | ||
228 | |||
229 | // Export to a file, because the MSI API's require us to provide a file path on disk | ||
230 | string certPath = Path.Combine(this.Context.IntermediateFolder, "MsiDigitalCertificate"); | ||
231 | Directory.CreateDirectory(certPath); | ||
232 | certPath = Path.Combine(certPath, string.Concat(cert2.Thumbprint, ".cer")); | ||
233 | File.Delete(certPath); | ||
234 | 201 | ||
235 | using (BinaryWriter writer = new BinaryWriter(File.Open(certPath, FileMode.Create))) | 202 | // Add it to our "add to MsiDigitalCertificate" table dictionary |
236 | { | 203 | Row digitalCertificateRow = digitalCertificateTable.CreateRow(null); |
237 | writer.Write(cert2.RawData); | 204 | digitalCertificateRow[0] = certificateGeneratedId; |
238 | writer.Close(); | ||
239 | } | ||
240 | 205 | ||
241 | // Now set the file path on disk where this binary stream will be picked up at import time | 206 | // Export to a file, because the MSI API's require us to provide a file path on disk |
242 | digitalCertificateRow[1] = string.Concat(cert2.Thumbprint, ".cer"); | 207 | string certPath = Path.Combine(this.Context.IntermediateFolder, "MsiDigitalCertificate"); |
208 | Directory.CreateDirectory(certPath); | ||
209 | certPath = Path.Combine(certPath, string.Concat(cert2.Thumbprint, ".cer")); | ||
210 | File.Delete(certPath); | ||
243 | 211 | ||
244 | certificates.Add(cert2.Thumbprint, certificateGeneratedId); | 212 | using (BinaryWriter writer = new BinaryWriter(File.Open(certPath, FileMode.Create))) |
213 | { | ||
214 | writer.Write(cert2.RawData); | ||
215 | writer.Close(); | ||
245 | } | 216 | } |
246 | 217 | ||
247 | digitalSignatureRow = digitalSignatureTable.CreateRow(null); | 218 | // Now set the file path on disk where this binary stream will be picked up at import time |
219 | digitalCertificateRow[1] = string.Concat(cert2.Thumbprint, ".cer"); | ||
248 | 220 | ||
249 | digitalSignatureRow[0] = "Media"; | 221 | certificates.Add(cert2.Thumbprint, certificateGeneratedId); |
250 | digitalSignatureRow[1] = cabId; | ||
251 | digitalSignatureRow[2] = certificates[cert2.Thumbprint]; | ||
252 | } | 222 | } |
223 | |||
224 | digitalSignatureRow = digitalSignatureTable.CreateRow(null); | ||
225 | |||
226 | digitalSignatureRow[0] = "Media"; | ||
227 | digitalSignatureRow[1] = cabId; | ||
228 | digitalSignatureRow[2] = certificates[cert2.Thumbprint]; | ||
253 | } | 229 | } |
254 | } | 230 | } |
255 | 231 | ||
@@ -275,7 +251,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe | |||
275 | 251 | ||
276 | certificates = null; | 252 | certificates = null; |
277 | 253 | ||
278 | // If we did find external cabs but none of them were signed, give a warning | 254 | // If we did find external cabs but not all of them were signed, give a warning |
279 | if (foundUnsignedExternals) | 255 | if (foundUnsignedExternals) |
280 | { | 256 | { |
281 | this.Messaging.Write(WarningMessages.ExternalCabsAreNotSigned(this.Context.InputFilePath)); | 257 | this.Messaging.Write(WarningMessages.ExternalCabsAreNotSigned(this.Context.InputFilePath)); |
diff --git a/src/WixToolset.Core.WindowsInstaller/Msi/View.cs b/src/WixToolset.Core.WindowsInstaller/Msi/View.cs index 1beb72da..0fb7fc62 100644 --- a/src/WixToolset.Core.WindowsInstaller/Msi/View.cs +++ b/src/WixToolset.Core.WindowsInstaller/Msi/View.cs | |||
@@ -3,6 +3,8 @@ | |||
3 | namespace WixToolset.Core.WindowsInstaller.Msi | 3 | namespace WixToolset.Core.WindowsInstaller.Msi |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections; | ||
7 | using System.Collections.Generic; | ||
6 | using System.Globalization; | 8 | using System.Globalization; |
7 | 9 | ||
8 | /// <summary> | 10 | /// <summary> |
@@ -110,6 +112,11 @@ namespace WixToolset.Core.WindowsInstaller.Msi | |||
110 | } | 112 | } |
111 | 113 | ||
112 | /// <summary> | 114 | /// <summary> |
115 | /// Enumerator that automatically disposes of the retrieved Records. | ||
116 | /// </summary> | ||
117 | public IEnumerable<Record> Records => new ViewEnumerable(this); | ||
118 | |||
119 | /// <summary> | ||
113 | /// Executes a view with no customizable parameters. | 120 | /// Executes a view with no customizable parameters. |
114 | /// </summary> | 121 | /// </summary> |
115 | public void Execute() | 122 | public void Execute() |
@@ -124,7 +131,7 @@ namespace WixToolset.Core.WindowsInstaller.Msi | |||
124 | /// <param name="record">Record containing parameters to be substituded into the view.</param> | 131 | /// <param name="record">Record containing parameters to be substituded into the view.</param> |
125 | public void Execute(Record record) | 132 | public void Execute(Record record) |
126 | { | 133 | { |
127 | int error = MsiInterop.MsiViewExecute(this.Handle, null == record ? 0 : record.Handle); | 134 | var error = MsiInterop.MsiViewExecute(this.Handle, null == record ? 0 : record.Handle); |
128 | if (0 != error) | 135 | if (0 != error) |
129 | { | 136 | { |
130 | throw new MsiException(error); | 137 | throw new MsiException(error); |
@@ -137,9 +144,7 @@ namespace WixToolset.Core.WindowsInstaller.Msi | |||
137 | /// <returns>Returns the fetched record; otherwise null.</returns> | 144 | /// <returns>Returns the fetched record; otherwise null.</returns> |
138 | public Record Fetch() | 145 | public Record Fetch() |
139 | { | 146 | { |
140 | uint recordHandle; | 147 | var error = MsiInterop.MsiViewFetch(this.Handle, out var recordHandle); |
141 | |||
142 | int error = MsiInterop.MsiViewFetch(this.Handle, out recordHandle); | ||
143 | if (259 == error) | 148 | if (259 == error) |
144 | { | 149 | { |
145 | return null; | 150 | return null; |
@@ -183,5 +188,75 @@ namespace WixToolset.Core.WindowsInstaller.Msi | |||
183 | 188 | ||
184 | return new Record(recordHandle); | 189 | return new Record(recordHandle); |
185 | } | 190 | } |
191 | |||
192 | private class ViewEnumerable : IEnumerable<Record> | ||
193 | { | ||
194 | private readonly View view; | ||
195 | |||
196 | public ViewEnumerable(View view) => this.view = view; | ||
197 | |||
198 | public IEnumerator<Record> GetEnumerator() => new ViewEnumerator(this.view); | ||
199 | |||
200 | IEnumerator IEnumerable.GetEnumerator() => new ViewEnumerator(this.view); | ||
201 | } | ||
202 | |||
203 | private class ViewEnumerator : IEnumerator<Record> | ||
204 | { | ||
205 | private readonly View view; | ||
206 | private readonly List<Record> records = new List<Record>(); | ||
207 | private int position = -1; | ||
208 | private bool disposed; | ||
209 | |||
210 | public ViewEnumerator(View view) => this.view = view; | ||
211 | |||
212 | public Record Current => this.records[this.position]; | ||
213 | |||
214 | object IEnumerator.Current => this.records[this.position]; | ||
215 | |||
216 | public bool MoveNext() | ||
217 | { | ||
218 | if (this.position + 1 >= this.records.Count) | ||
219 | { | ||
220 | var record = this.view.Fetch(); | ||
221 | |||
222 | if (record == null) | ||
223 | { | ||
224 | return false; | ||
225 | } | ||
226 | |||
227 | this.records.Add(record); | ||
228 | this.position = this.records.Count - 1; | ||
229 | } | ||
230 | else | ||
231 | { | ||
232 | ++this.position; | ||
233 | } | ||
234 | |||
235 | return true; | ||
236 | } | ||
237 | |||
238 | public void Reset() => this.position = -1; | ||
239 | |||
240 | public void Dispose() | ||
241 | { | ||
242 | this.Dispose(true); | ||
243 | } | ||
244 | |||
245 | protected virtual void Dispose(bool disposing) | ||
246 | { | ||
247 | if (!this.disposed) | ||
248 | { | ||
249 | if (disposing) | ||
250 | { | ||
251 | foreach (var record in this.records) | ||
252 | { | ||
253 | record.Dispose(); | ||
254 | } | ||
255 | } | ||
256 | |||
257 | this.disposed = true; | ||
258 | } | ||
259 | } | ||
260 | } | ||
186 | } | 261 | } |
187 | } | 262 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs index 557500e8..fb4b4ee3 100644 --- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs | |||
@@ -121,142 +121,125 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
121 | // get the normal tables | 121 | // get the normal tables |
122 | using (var tablesView = this.Database.OpenExecuteView("SELECT * FROM _Tables")) | 122 | using (var tablesView = this.Database.OpenExecuteView("SELECT * FROM _Tables")) |
123 | { | 123 | { |
124 | while (true) | 124 | foreach (var tableRecord in tablesView.Records) |
125 | { | 125 | { |
126 | using (var tableRecord = tablesView.Fetch()) | 126 | var tableName = tableRecord.GetString(1); |
127 | { | ||
128 | if (null == tableRecord) | ||
129 | { | ||
130 | break; | ||
131 | } | ||
132 | 127 | ||
133 | var tableName = tableRecord.GetString(1); | 128 | using (var tableView = this.Database.OpenExecuteView(String.Format(CultureInfo.InvariantCulture, "SELECT * FROM `{0}`", tableName))) |
129 | { | ||
130 | var tableDefinition = this.GetTableDefinition(tableName, tableView, validationView); | ||
131 | var table = new Table(tableDefinition); | ||
134 | 132 | ||
135 | using (var tableView = this.Database.OpenExecuteView(String.Format(CultureInfo.InvariantCulture, "SELECT * FROM `{0}`", tableName))) | 133 | foreach (var rowRecord in tableView.Records) |
136 | { | 134 | { |
137 | var tableDefinition = this.GetTableDefinition(tableName, tableView, validationView); | 135 | var recordCount = rowRecord.GetFieldCount(); |
138 | var table = new Table(tableDefinition); | 136 | var row = table.CreateRow(output.SourceLineNumbers); |
139 | 137 | ||
140 | while (true) | 138 | for (var i = 0; recordCount > i && row.Fields.Length > i; i++) |
141 | { | 139 | { |
142 | using (var rowRecord = tableView.Fetch()) | 140 | if (rowRecord.IsNull(i + 1)) |
143 | { | 141 | { |
144 | if (null == rowRecord) | 142 | if (!row.Fields[i].Column.Nullable) |
145 | { | 143 | { |
146 | break; | 144 | // TODO: display an error for a null value in a non-nullable field OR |
145 | // display a warning and put an empty string in the value to let the compiler handle it | ||
146 | // (the second option is risky because the later code may make certain assumptions about | ||
147 | // the contents of a row value) | ||
147 | } | 148 | } |
148 | 149 | } | |
149 | var recordCount = rowRecord.GetFieldCount(); | 150 | else |
150 | var row = table.CreateRow(output.SourceLineNumbers); | 151 | { |
151 | 152 | switch (row.Fields[i].Column.Type) | |
152 | for (var i = 0; recordCount > i && row.Fields.Length > i; i++) | ||
153 | { | 153 | { |
154 | if (rowRecord.IsNull(i + 1)) | 154 | case ColumnType.Number: |
155 | { | 155 | var success = false; |
156 | if (!row.Fields[i].Column.Nullable) | 156 | var intValue = rowRecord.GetInteger(i + 1); |
157 | if (row.Fields[i].Column.IsLocalizable) | ||
157 | { | 158 | { |
158 | // TODO: display an error for a null value in a non-nullable field OR | 159 | success = row.BestEffortSetField(i, Convert.ToString(intValue, CultureInfo.InvariantCulture)); |
159 | // display a warning and put an empty string in the value to let the compiler handle it | ||
160 | // (the second option is risky because the later code may make certain assumptions about | ||
161 | // the contents of a row value) | ||
162 | } | 160 | } |
163 | } | 161 | else |
164 | else | ||
165 | { | ||
166 | switch (row.Fields[i].Column.Type) | ||
167 | { | 162 | { |
168 | case ColumnType.Number: | 163 | success = row.BestEffortSetField(i, intValue); |
169 | var success = false; | 164 | } |
170 | var intValue = rowRecord.GetInteger(i + 1); | ||
171 | if (row.Fields[i].Column.IsLocalizable) | ||
172 | { | ||
173 | success = row.BestEffortSetField(i, Convert.ToString(intValue, CultureInfo.InvariantCulture)); | ||
174 | } | ||
175 | else | ||
176 | { | ||
177 | success = row.BestEffortSetField(i, intValue); | ||
178 | } | ||
179 | 165 | ||
180 | if (!success) | 166 | if (!success) |
181 | { | 167 | { |
182 | this.Messaging.Write(WarningMessages.BadColumnDataIgnored(row.SourceLineNumbers, Convert.ToString(intValue, CultureInfo.InvariantCulture), tableName, row.Fields[i].Column.Name)); | 168 | this.Messaging.Write(WarningMessages.BadColumnDataIgnored(row.SourceLineNumbers, Convert.ToString(intValue, CultureInfo.InvariantCulture), tableName, row.Fields[i].Column.Name)); |
183 | } | 169 | } |
184 | break; | 170 | break; |
185 | case ColumnType.Object: | 171 | case ColumnType.Object: |
186 | var sourceFile = "FILE NOT EXPORTED, USE THE dark.exe -x OPTION TO EXPORT BINARIES"; | 172 | var sourceFile = "FILE NOT EXPORTED, USE THE dark.exe -x OPTION TO EXPORT BINARIES"; |
187 | 173 | ||
188 | if (null != this.ExportBasePath) | 174 | if (null != this.ExportBasePath) |
189 | { | 175 | { |
190 | var relativeSourceFile = Path.Combine(tableName, row.GetPrimaryKey('.')); | 176 | var relativeSourceFile = Path.Combine(tableName, row.GetPrimaryKey('.')); |
191 | sourceFile = Path.Combine(this.ExportBasePath, relativeSourceFile); | 177 | sourceFile = Path.Combine(this.ExportBasePath, relativeSourceFile); |
192 | 178 | ||
193 | // ensure the parent directory exists | 179 | // ensure the parent directory exists |
194 | System.IO.Directory.CreateDirectory(Path.Combine(this.ExportBasePath, tableName)); | 180 | System.IO.Directory.CreateDirectory(Path.Combine(this.ExportBasePath, tableName)); |
195 | 181 | ||
196 | using (var fs = System.IO.File.Create(sourceFile)) | 182 | using (var fs = System.IO.File.Create(sourceFile)) |
197 | { | 183 | { |
198 | int bytesRead; | 184 | int bytesRead; |
199 | var buffer = new byte[512]; | 185 | var buffer = new byte[512]; |
200 | 186 | ||
201 | while (0 != (bytesRead = rowRecord.GetStream(i + 1, buffer, buffer.Length))) | 187 | while (0 != (bytesRead = rowRecord.GetStream(i + 1, buffer, buffer.Length))) |
202 | { | 188 | { |
203 | fs.Write(buffer, 0, bytesRead); | 189 | fs.Write(buffer, 0, bytesRead); |
204 | } | ||
205 | } | 190 | } |
206 | |||
207 | this.exportedFiles.Add(sourceFile); | ||
208 | } | 191 | } |
209 | 192 | ||
210 | row[i] = sourceFile; | 193 | this.exportedFiles.Add(sourceFile); |
211 | break; | 194 | } |
212 | default: | ||
213 | var value = rowRecord.GetString(i + 1); | ||
214 | 195 | ||
215 | switch (row.Fields[i].Column.Category) | 196 | row[i] = sourceFile; |
216 | { | 197 | break; |
198 | default: | ||
199 | var value = rowRecord.GetString(i + 1); | ||
200 | |||
201 | switch (row.Fields[i].Column.Category) | ||
202 | { | ||
217 | case ColumnCategory.Guid: | 203 | case ColumnCategory.Guid: |
218 | value = value.ToUpper(CultureInfo.InvariantCulture); | 204 | value = value.ToUpper(CultureInfo.InvariantCulture); |
219 | break; | 205 | break; |
220 | } | 206 | } |
221 | 207 | ||
222 | // de-modularize | 208 | // de-modularize |
223 | if (!this.SuppressDemodularization && OutputType.Module == output.Type && ColumnModularizeType.None != row.Fields[i].Column.ModularizeType) | 209 | if (!this.SuppressDemodularization && OutputType.Module == output.Type && ColumnModularizeType.None != row.Fields[i].Column.ModularizeType) |
224 | { | 210 | { |
225 | var modularization = new Regex(@"\.[0-9A-Fa-f]{8}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{12}"); | 211 | var modularization = new Regex(@"\.[0-9A-Fa-f]{8}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{12}"); |
226 | 212 | ||
227 | if (null == modularizationGuid) | 213 | if (null == modularizationGuid) |
214 | { | ||
215 | var match = modularization.Match(value); | ||
216 | if (match.Success) | ||
228 | { | 217 | { |
229 | var match = modularization.Match(value); | 218 | modularizationGuid = String.Concat('{', match.Value.Substring(1).Replace('_', '-'), '}'); |
230 | if (match.Success) | ||
231 | { | ||
232 | modularizationGuid = String.Concat('{', match.Value.Substring(1).Replace('_', '-'), '}'); | ||
233 | } | ||
234 | } | 219 | } |
235 | |||
236 | value = modularization.Replace(value, String.Empty); | ||
237 | } | 220 | } |
238 | 221 | ||
239 | // escape "$(" for the preprocessor | 222 | value = modularization.Replace(value, String.Empty); |
240 | value = value.Replace("$(", "$$("); | 223 | } |
241 | 224 | ||
242 | // escape things that look like wix variables | 225 | // escape "$(" for the preprocessor |
243 | var matches = Common.WixVariableRegex.Matches(value); | 226 | value = value.Replace("$(", "$$("); |
244 | for (var j = matches.Count - 1; 0 <= j; j--) | ||
245 | { | ||
246 | value = value.Insert(matches[j].Index, "!"); | ||
247 | } | ||
248 | 227 | ||
249 | row[i] = value; | 228 | // escape things that look like wix variables |
250 | break; | 229 | var matches = Common.WixVariableRegex.Matches(value); |
230 | for (var j = matches.Count - 1; 0 <= j; j--) | ||
231 | { | ||
232 | value = value.Insert(matches[j].Index, "!"); | ||
251 | } | 233 | } |
252 | } | 234 | |
235 | row[i] = value; | ||
236 | break; | ||
253 | } | 237 | } |
254 | } | 238 | } |
255 | } | 239 | } |
256 | |||
257 | output.Tables.Add(table); | ||
258 | } | 240 | } |
259 | 241 | ||
242 | output.Tables.Add(table); | ||
260 | } | 243 | } |
261 | } | 244 | } |
262 | } | 245 | } |
@@ -634,82 +617,82 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
634 | { | 617 | { |
635 | switch (table.Name) | 618 | switch (table.Name) |
636 | { | 619 | { |
637 | case "WixFile": | 620 | case "WixFile": |
638 | case "MsiFileHash": | 621 | case "MsiFileHash": |
639 | ConnectTableToSection(table, fileSectionIdIndex, 0); | 622 | ConnectTableToSection(table, fileSectionIdIndex, 0); |
640 | break; | 623 | break; |
641 | case "MsiAssembly": | 624 | case "MsiAssembly": |
642 | case "MsiAssemblyName": | 625 | case "MsiAssemblyName": |
643 | ConnectTableToSection(table, componentSectionIdIndex, 0); | 626 | ConnectTableToSection(table, componentSectionIdIndex, 0); |
644 | break; | 627 | break; |
645 | case "MsiPackageCertificate": | 628 | case "MsiPackageCertificate": |
646 | case "MsiPatchCertificate": | 629 | case "MsiPatchCertificate": |
647 | ConnectTableToSection(table, digitalCertificateSectionIdIndex, 1); | 630 | ConnectTableToSection(table, digitalCertificateSectionIdIndex, 1); |
648 | break; | 631 | break; |
649 | case "CreateFolder": | 632 | case "CreateFolder": |
650 | case "FeatureComponents": | 633 | case "FeatureComponents": |
651 | case "MoveFile": | 634 | case "MoveFile": |
652 | case "ReserveCost": | 635 | case "ReserveCost": |
653 | case "ODBCTranslator": | 636 | case "ODBCTranslator": |
654 | ConnectTableToSection(table, componentSectionIdIndex, 1); | 637 | ConnectTableToSection(table, componentSectionIdIndex, 1); |
655 | break; | 638 | break; |
656 | case "TypeLib": | 639 | case "TypeLib": |
657 | ConnectTableToSection(table, componentSectionIdIndex, 2); | 640 | ConnectTableToSection(table, componentSectionIdIndex, 2); |
658 | break; | 641 | break; |
659 | case "Shortcut": | 642 | case "Shortcut": |
660 | case "Environment": | 643 | case "Environment": |
661 | ConnectTableToSection(table, componentSectionIdIndex, 3); | 644 | ConnectTableToSection(table, componentSectionIdIndex, 3); |
662 | break; | 645 | break; |
663 | case "RemoveRegistry": | 646 | case "RemoveRegistry": |
664 | ConnectTableToSection(table, componentSectionIdIndex, 4); | 647 | ConnectTableToSection(table, componentSectionIdIndex, 4); |
665 | break; | 648 | break; |
666 | case "ServiceControl": | 649 | case "ServiceControl": |
667 | ConnectTableToSection(table, componentSectionIdIndex, 5); | 650 | ConnectTableToSection(table, componentSectionIdIndex, 5); |
668 | break; | 651 | break; |
669 | case "IniFile": | 652 | case "IniFile": |
670 | case "RemoveIniFile": | 653 | case "RemoveIniFile": |
671 | ConnectTableToSection(table, componentSectionIdIndex, 7); | 654 | ConnectTableToSection(table, componentSectionIdIndex, 7); |
672 | break; | 655 | break; |
673 | case "AppId": | 656 | case "AppId": |
674 | ConnectTableToSection(table, appIdSectionIdIndex, 0); | 657 | ConnectTableToSection(table, appIdSectionIdIndex, 0); |
675 | break; | 658 | break; |
676 | case "Condition": | 659 | case "Condition": |
677 | ConnectTableToSection(table, featureSectionIdIndex, 0); | 660 | ConnectTableToSection(table, featureSectionIdIndex, 0); |
678 | break; | 661 | break; |
679 | case "ODBCSourceAttribute": | 662 | case "ODBCSourceAttribute": |
680 | ConnectTableToSection(table, odbcDataSourceSectionIdIndex, 0); | 663 | ConnectTableToSection(table, odbcDataSourceSectionIdIndex, 0); |
681 | break; | 664 | break; |
682 | case "ODBCAttribute": | 665 | case "ODBCAttribute": |
683 | ConnectTableToSection(table, odbcDriverSectionIdIndex, 0); | 666 | ConnectTableToSection(table, odbcDriverSectionIdIndex, 0); |
684 | break; | 667 | break; |
685 | case "AdminExecuteSequence": | 668 | case "AdminExecuteSequence": |
686 | case "AdminUISequence": | 669 | case "AdminUISequence": |
687 | case "AdvtExecuteSequence": | 670 | case "AdvtExecuteSequence": |
688 | case "AdvtUISequence": | 671 | case "AdvtUISequence": |
689 | case "InstallExecuteSequence": | 672 | case "InstallExecuteSequence": |
690 | case "InstallUISequence": | 673 | case "InstallUISequence": |
691 | ConnectTableToSection(table, customActionSectionIdIndex, 0); | 674 | ConnectTableToSection(table, customActionSectionIdIndex, 0); |
692 | break; | 675 | break; |
693 | case "LockPermissions": | 676 | case "LockPermissions": |
694 | case "MsiLockPermissions": | 677 | case "MsiLockPermissions": |
695 | foreach (var row in table.Rows) | 678 | foreach (var row in table.Rows) |
696 | { | ||
697 | var lockObject = (string)row[0]; | ||
698 | var tableName = (string)row[1]; | ||
699 | switch (tableName) | ||
700 | { | 679 | { |
701 | case "File": | 680 | var lockObject = (string)row[0]; |
702 | row.SectionId = (string)fileSectionIdIndex[lockObject]; | 681 | var tableName = (string)row[1]; |
703 | break; | 682 | switch (tableName) |
704 | case "Registry": | 683 | { |
705 | row.SectionId = (string)registrySectionIdIndex[lockObject]; | 684 | case "File": |
706 | break; | 685 | row.SectionId = (string)fileSectionIdIndex[lockObject]; |
707 | case "ServiceInstall": | 686 | break; |
708 | row.SectionId = (string)serviceInstallSectionIdIndex[lockObject]; | 687 | case "Registry": |
709 | break; | 688 | row.SectionId = (string)registrySectionIdIndex[lockObject]; |
689 | break; | ||
690 | case "ServiceInstall": | ||
691 | row.SectionId = (string)serviceInstallSectionIdIndex[lockObject]; | ||
692 | break; | ||
693 | } | ||
710 | } | 694 | } |
711 | } | 695 | break; |
712 | break; | ||
713 | } | 696 | } |
714 | } | 697 | } |
715 | 698 | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Validator.cs b/src/WixToolset.Core.WindowsInstaller/Validator.cs index 1c9cdc2f..72b09ebc 100644 --- a/src/WixToolset.Core.WindowsInstaller/Validator.cs +++ b/src/WixToolset.Core.WindowsInstaller/Validator.cs | |||
@@ -201,21 +201,13 @@ namespace WixToolset.Core.WindowsInstaller | |||
201 | List<string> actions = new List<string>(); | 201 | List<string> actions = new List<string>(); |
202 | using (View view = database.OpenExecuteView("SELECT `Action` FROM `_ICESequence` ORDER BY `Sequence`")) | 202 | using (View view = database.OpenExecuteView("SELECT `Action` FROM `_ICESequence` ORDER BY `Sequence`")) |
203 | { | 203 | { |
204 | while (true) | 204 | foreach (Record record in view.Records) |
205 | { | 205 | { |
206 | using (Record record = view.Fetch()) | 206 | string action = record.GetString(1); |
207 | { | ||
208 | if (null == record) | ||
209 | { | ||
210 | break; | ||
211 | } | ||
212 | 207 | ||
213 | string action = record.GetString(1); | 208 | if ((this.SuppressedICEs == null || !this.SuppressedICEs.Contains(action)) && (this.ICEs == null || this.ICEs.Contains(action))) |
214 | 209 | { | |
215 | if ((this.SuppressedICEs == null || !this.SuppressedICEs.Contains(action)) && (this.ICEs == null || this.ICEs.Contains(action))) | 210 | actions.Add(action); |
216 | { | ||
217 | actions.Add(action); | ||
218 | } | ||
219 | } | 211 | } |
220 | } | 212 | } |
221 | } | 213 | } |
diff --git a/src/WixToolset.Core/CommandLine/BuildCommand.cs b/src/WixToolset.Core/CommandLine/BuildCommand.cs index 5ee60984..023a3c1e 100644 --- a/src/WixToolset.Core/CommandLine/BuildCommand.cs +++ b/src/WixToolset.Core/CommandLine/BuildCommand.cs | |||
@@ -591,7 +591,7 @@ namespace WixToolset.Core.CommandLine | |||
591 | this.OutputType = Path.GetExtension(this.OutputFile); | 591 | this.OutputType = Path.GetExtension(this.OutputFile); |
592 | } | 592 | } |
593 | 593 | ||
594 | switch (this.OutputType.ToLowerInvariant()) | 594 | switch (this.OutputType?.ToLowerInvariant()) |
595 | { | 595 | { |
596 | case "bundle": | 596 | case "bundle": |
597 | case ".exe": | 597 | case ".exe": |