aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2020-01-13 09:10:13 -0800
committerRob Mensching <rob@firegiant.com>2020-01-13 14:19:45 -0800
commit94b941ee95a294228516097c269e27dfa41593ab (patch)
tree208cb36a5a6a3e17f5d458cfaa679d6ca1a76e15 /src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs
parenta2b1235d9c0dfba48b1badac428d89d1137da698 (diff)
downloadwix-94b941ee95a294228516097c269e27dfa41593ab.tar.gz
wix-94b941ee95a294228516097c269e27dfa41593ab.tar.bz2
wix-94b941ee95a294228516097c269e27dfa41593ab.zip
Provide Record enumerator on View that disposes fetched Records
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs242
1 files changed, 109 insertions, 133 deletions
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));