aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/Cab/WixCreateCab.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/Cab/WixCreateCab.cs')
-rw-r--r--src/WixToolset.Core/Cab/WixCreateCab.cs249
1 files changed, 0 insertions, 249 deletions
diff --git a/src/WixToolset.Core/Cab/WixCreateCab.cs b/src/WixToolset.Core/Cab/WixCreateCab.cs
deleted file mode 100644
index 4ebdd1c0..00000000
--- a/src/WixToolset.Core/Cab/WixCreateCab.cs
+++ /dev/null
@@ -1,249 +0,0 @@
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.Core.Cab
4{
5 using System;
6 using System.Globalization;
7 using System.IO;
8 using System.Runtime.InteropServices;
9 using WixToolset.Core.Bind;
10 using WixToolset.Core.Native;
11 using WixToolset.Data;
12
13 /// <summary>
14 /// Wrapper class around interop with wixcab.dll to compress files into a cabinet.
15 /// </summary>
16 public sealed class WixCreateCab : IDisposable
17 {
18 private static readonly string CompressionLevelVariable = "WIX_COMPRESSION_LEVEL";
19 private IntPtr handle = IntPtr.Zero;
20 private bool disposed;
21 private int maxSize;
22
23 /// <summary>
24 /// Creates a cabinet.
25 /// </summary>
26 /// <param name="cabName">Name of cabinet to create.</param>
27 /// <param name="cabDir">Directory to create cabinet in.</param>
28 /// <param name="maxFiles">Maximum number of files that will be added to cabinet.</param>
29 /// <param name="maxSize">Maximum size of cabinet.</param>
30 /// <param name="maxThresh">Maximum threshold for each cabinet.</param>
31 /// <param name="compressionLevel">Level of compression to apply.</param>
32 public WixCreateCab(string cabName, string cabDir, int maxFiles, int maxSize, int maxThresh, CompressionLevel compressionLevel)
33 {
34 string compressionLevelVariable = Environment.GetEnvironmentVariable(CompressionLevelVariable);
35 this.maxSize = maxSize;
36
37 try
38 {
39 // Override authored compression level if environment variable is present.
40 if (!String.IsNullOrEmpty(compressionLevelVariable))
41 {
42 compressionLevel = WixCreateCab.CompressionLevelFromString(compressionLevelVariable);
43 }
44 }
45 catch (WixException)
46 {
47 throw new WixException(WixErrors.IllegalEnvironmentVariable(CompressionLevelVariable, compressionLevelVariable));
48 }
49
50 if (String.IsNullOrEmpty(cabDir))
51 {
52 cabDir = Directory.GetCurrentDirectory();
53 }
54
55 try
56 {
57 NativeMethods.CreateCabBegin(cabName, cabDir, (uint)maxFiles, (uint)maxSize, (uint)maxThresh, (uint)compressionLevel, out this.handle);
58 }
59 catch (COMException ce)
60 {
61 // If we get a "the file exists" error, we must have a full temp directory - so report the issue
62 if (0x80070050 == unchecked((uint)ce.ErrorCode))
63 {
64 throw new WixException(WixErrors.FullTempDirectory("WSC", Path.GetTempPath()));
65 }
66
67 throw;
68 }
69 }
70
71 /// <summary>
72 /// Destructor for cabinet creation.
73 /// </summary>
74 ~WixCreateCab()
75 {
76 this.Dispose();
77 }
78
79 /// <summary>
80 /// Converts a compression level from its string to its enum value.
81 /// </summary>
82 /// <param name="compressionLevel">Compression level as a string.</param>
83 /// <returns>CompressionLevel enum value</returns>
84 public static CompressionLevel CompressionLevelFromString(string compressionLevel)
85 {
86 switch (compressionLevel.ToLower(CultureInfo.InvariantCulture))
87 {
88 case "low":
89 return CompressionLevel.Low;
90 case "medium":
91 return CompressionLevel.Medium;
92 case "high":
93 return CompressionLevel.High;
94 case "none":
95 return CompressionLevel.None;
96 case "mszip":
97 return CompressionLevel.Mszip;
98 default:
99 throw new WixException(WixErrors.IllegalCompressionLevel(compressionLevel));
100 }
101 }
102
103 /// <summary>
104 /// Adds a file to the cabinet.
105 /// </summary>
106 /// <param name="fileFacade">The file facade of the file to add.</param>
107 public void AddFile(FileFacade fileFacade)
108 {
109 MsiInterop.MSIFILEHASHINFO hashInterop = new MsiInterop.MSIFILEHASHINFO();
110
111 if (null != fileFacade.Hash)
112 {
113 hashInterop.FileHashInfoSize = 20;
114 hashInterop.Data0 = (int)fileFacade.Hash[2];
115 hashInterop.Data1 = (int)fileFacade.Hash[3];
116 hashInterop.Data2 = (int)fileFacade.Hash[4];
117 hashInterop.Data3 = (int)fileFacade.Hash[5];
118
119 this.AddFile(fileFacade.WixFile.Source, fileFacade.File.File, hashInterop);
120 }
121 else
122 {
123 this.AddFile(fileFacade.WixFile.Source, fileFacade.File.File);
124 }
125 }
126
127 /// <summary>
128 /// Adds a file to the cabinet.
129 /// </summary>
130 /// <param name="file">The file to add.</param>
131 /// <param name="token">The token for the file.</param>
132 public void AddFile(string file, string token)
133 {
134 this.AddFile(file, token, null);
135 }
136
137 /// <summary>
138 /// Adds a file to the cabinet with an optional MSI file hash.
139 /// </summary>
140 /// <param name="file">The file to add.</param>
141 /// <param name="token">The token for the file.</param>
142 /// <param name="fileHash">The MSI file hash of the file.</param>
143 private void AddFile(string file, string token, MsiInterop.MSIFILEHASHINFO fileHash)
144 {
145 try
146 {
147 NativeMethods.CreateCabAddFile(file, token, fileHash, this.handle);
148 }
149 catch (COMException ce)
150 {
151 if (0x80004005 == unchecked((uint)ce.ErrorCode)) // E_FAIL
152 {
153 throw new WixException(WixErrors.CreateCabAddFileFailed());
154 }
155 else if (0x80070070 == unchecked((uint)ce.ErrorCode)) // ERROR_DISK_FULL
156 {
157 throw new WixException(WixErrors.CreateCabInsufficientDiskSpace());
158 }
159 else
160 {
161 throw;
162 }
163 }
164 catch (DirectoryNotFoundException)
165 {
166 throw new WixFileNotFoundException(file);
167 }
168 catch (FileNotFoundException)
169 {
170 throw new WixFileNotFoundException(file);
171 }
172 }
173
174 /// <summary>
175 /// Complete/commit the cabinet - this must be called before Dispose so that errors will be
176 /// reported on the same thread.
177 /// This Complete should be used with no Cabinet splitting as it has the split cabinet names callback address as Zero
178 /// </summary>
179 public void Complete()
180 {
181 this.Complete(IntPtr.Zero);
182 }
183
184 /// <summary>
185 /// Complete/commit the cabinet - this must be called before Dispose so that errors will be
186 /// reported on the same thread.
187 /// </summary>
188 /// <param name="newCabNamesCallBackAddress">Address of Binder's callback function for Cabinet Splitting</param>
189 public void Complete(IntPtr newCabNamesCallBackAddress)
190 {
191 if (IntPtr.Zero != this.handle)
192 {
193 try
194 {
195 if (newCabNamesCallBackAddress != IntPtr.Zero && this.maxSize != 0)
196 {
197 NativeMethods.CreateCabFinish(this.handle, newCabNamesCallBackAddress);
198 }
199 else
200 {
201 NativeMethods.CreateCabFinish(this.handle, IntPtr.Zero);
202 }
203
204 GC.SuppressFinalize(this);
205 this.disposed = true;
206 }
207 catch (COMException ce)
208 {
209 if (0x80004005 == unchecked((uint)ce.ErrorCode)) // E_FAIL
210 {
211 // This error seems to happen, among other situations, when cabbing more than 0xFFFF files
212 throw new WixException(WixErrors.FinishCabFailed());
213 }
214 else if (0x80070070 == unchecked((uint)ce.ErrorCode)) // ERROR_DISK_FULL
215 {
216 throw new WixException(WixErrors.CreateCabInsufficientDiskSpace());
217 }
218 else
219 {
220 throw;
221 }
222 }
223 finally
224 {
225 this.handle = IntPtr.Zero;
226 }
227 }
228 }
229
230 /// <summary>
231 /// Cancels ("rolls back") the creation of the cabinet.
232 /// Don't throw WiX errors from here, because we're in a different thread, and they won't be reported correctly.
233 /// </summary>
234 public void Dispose()
235 {
236 if (!this.disposed)
237 {
238 if (IntPtr.Zero != this.handle)
239 {
240 NativeMethods.CreateCabCancel(this.handle);
241 this.handle = IntPtr.Zero;
242 }
243
244 GC.SuppressFinalize(this);
245 this.disposed = true;
246 }
247 }
248 }
249}